🎄 A Festive CiviCRM Catch-Up in Birmingham

CiviCRM
civicrm.org
2025-12-16 15:48:53
🎄 A Festive CiviCRM Catch-Up in Birmingham As the year drew to a close, we were delighted to bring the UK CiviCRM community together for a festive meetup in Birmingham on 9 December. The meetup began in the best possible way, with dinner at a lovely local restaurant, giving everyone a relaxed ...
Original Article

🎄 A Festive CiviCRM Catch-Up in Birmingham

As the year drew to a close, we were delighted to bring the UK CiviCRM community together for a festive meetup in Birmingham on 9 December .

The meetup began in the best possible way, with dinner at a lovely local restaurant , giving everyone a relaxed opportunity to catch up, share experiences from the year, and enjoy some seasonal cheer. 🍽️✨

The following day, conversations continued with an open and wide-ranging discussion about the CiviCRM world — from current challenges and successes to ideas for strengthening and supporting the UK community.

Looking ahead, there was plenty of enthusiasm for future activities and events , including:

  • A potential UK CiviCRM meetup in Manchester in late February 2026
  • The idea of a one-day, user-focused CiviCamp , possibly hosted in Birmingham or London in May 2026
  • More administration-focused training sessions , responding to ongoing demand from users
  • And a potential end-of-year mini sprint , giving the community a chance to collaborate on practical improvements and shared goals

It’s encouraging to see so much energy and willingness to get involved as we look ahead to the coming year.

👉 For updates and further information, please keep an eye on the Mattermost site , under the UK Meetups channel .

Wishing everyone in the CiviCRM community a very Merry Christmas and a Happy New Year — we look forward to seeing you again soon!

Beyond RC4 for Windows Authentication

Hacker News
www.microsoft.com
2025-12-17 17:14:21
Comments...
Original Article

New PowerShell scripts

Instead of manually reviewing the Security Event log on your domain controllers to find problematic RC4 usage via events 4768 and 4769, let’s introduce two new PowerShell scripts that are available to you on the Microsoft Kerberos-Crypto GitHub repository.

List-AccountKeys.ps1

Use this PowerShell script to query the Security Event Log for the new Available Keys field. The script enumerates the keys that are available for the accounts it finds from the event logs, as well as the following information:

  • The time at which an event happened
  • The account name
  • The account type
  • The account keys

PS C:\tools> .\List-AccountKeys.ps1

Time                  Name         Type Keys

----                  ----         ---- ----

1/21/2025 2:00:10 PM  LD1$      Machine {RC4, AES128-SHA96, AES256-SHA96, AES128-SHA256...}

1/21/2025 2:00:10 PM  AdminUser    User {RC4, AES128-SHA96, AES256-SHA96, AES128-SHA256...}

1/21/2025 6:50:34 PM  LD1$      Machine {RC4, AES128-SHA96, AES256-SHA96, AES128-SHA256...}

1/21/2025 6:50:34 PM  AdminUser    User {RC4, AES128-SHA96, AES256-SHA96, AES128-SHA256...}

1/21/2025 6:50:34 PM  LD1$      Machine {RC4, AES128-SHA96, AES256-SHA96, AES128-SHA256...}

In this case, the results show that there are AES128-SHA96 and AES256-SHA96 keys available for the accounts found in the logs, meaning these accounts will continue to work if RC4 is disabled.

Get-KerbEncryptionUsage.ps1

Use this PowerShell script to query the same events to see which encryption types Kerberos used within your environment. In this example, the requests used AES256-SHA96, which is a part of AES-SHA1.

PS C:\tools> .\Get-KerbEncryptionUsage.ps1

Time       : 1/21/2025 2:00:10 PM

Requestor  : ::1

Source     : AdminUser@CONTOSO.COM

Target     : LD1$

Type       : TGS

Ticket     : AES256-SHA96

SessionKey : AES256-SHA96

Time       : 1/21/2025 2:00:10 PM

Requestor  : 192.168.1.1

Source     : AdminUser

Target     : krbtgt

Type       : AS

Ticket     : AES256-SHA96

SessionKey : AES256-SHA96

With this script, you can try out additional filtering options on specific encryption algorithms. For example, use the RC4 filter to specifically find requests that used RC4:

PS C:\tools> .\Get-KerbEncryptionUsage.ps1 -Encryption RC4

You can also use security information and event management (SIEM) solutions, like Microsoft Sentinel, or built-in Windows event forwarding as described in So, you think you’re ready for enforcing AES for Kerberos? to query these logs.

AWS CEO says replacing junior devs with AI is 'one of the dumbest ideas'

Hacker News
www.finalroundai.com
2025-12-17 17:08:35
Comments...
Original Article

AWS CEO Junior Developers AI

AWS CEO Matt Garman outlined 3 solid reasons why companies should not focus on cutting junior developer roles, noting that they “ are actually the most experienced with the AI tools ”.

3 Reasons AI Should Not Replace Junior Developers

In a tech world obsessed with AI replacing human workers, Matt Garman, CEO of Amazon Web Services (AWS), is pushing back against one of the industry’s most popular cost-cutting ideas.

Speaking on WIRED’s The Big Interview podcast , Garman has a bold message for companies racing to cut costs with AI.

Matt Garman on Junior Developers

He was asked to explain why he once called replacing junior employees with AI “ one of the dumbest ideas ” he’d ever heard, and to expand on how he believes agentic AI will actually change the workplace in the coming years.

1) Junior Devs Often Know AI Tools Better

First, junior employees are often better with AI tools than senior staff.

“Number one, my experience is that many of the most junior folks are actually the most experienced with the AI tools. So they're actually most able to get the most out of them.”

Fresh grads have grown up with new technology, so they can adapt quickly. Many of them learn AI-powered tools while studying or during internships. They tend to explore new features, find quick methods to write code, and figure out how to get the best results from AI agents.

According to the 2025 Stack Overflow Developer Survey , 55.5% of early-career developers reported using AI tools daily in their development process, higher than for the experienced folks.

This comfort with new tools allows them to work more efficiently. In contrast, senior developers have established workflows and may take more time to adopt. Recent research shows that over half of Gen Z employees are actually helping senior colleagues upskill in AI.

2) Junior Developers Shouldn’t Be The Default Cost-Saving Move

Second, junior staff are usually the least expensive employees.

“Number two, they're usually the least expensive because they're right out of college, and they generally make less. So if you're thinking about cost optimization, they're not the only people you would want to optimize around.”

Junior employees usually get much less in salary and benefits, so removing them does not deliver huge savings. If a company is trying to save money, it doesn’t make that much financial sense.

So, when companies talk about increasing profit margins, junior employees should not be the default or only target. True optimization, Real cost-cutting means looking at the whole company because there are plenty of other places where expenses can be trimmed.

In fact, 30% of companies that laid off workers expecting savings ended up increasing expenses , and many had to rehire later.

3) Removing Juniors Breaks the Talent Pipeline

Third, companies need fresh talent.

“Three, at some point, that whole thing explodes on itself. If you have no talent pipeline that you're building and no junior people that you're mentoring and bringing up through the company, we often find that that's where we get some of the best ideas.”

Think of a company like a sports team. If you only keep veteran players and never recruit rookies, what happens when those veterans retire? You are left with no one who knows how to play the game.

Also, hiring people straight out of college brings new ways of thinking into the workplace. They have fresh ideas shaped by the latest trends, motivation to innovate.

More importantly, they form the foundation of a company’s future workforce. If a company decides to stop hiring junior employees altogether, it cuts off its own talent pipeline. Over time, that leads to fewer leaders to promote from within.

A Deloitte report also notes that the tech workforce is expected to grow at roughly twice the rate of the overall U.S. workforce, highlighting the demand for tech talent. Without a strong pipeline of junior developers coming in, companies might face a tech talent shortage.

When there are not enough junior hires being trained today, teams struggle to fill roles tomorrow, especially as projects scale.

Bottom Line

This isn’t just corporate talk. As the leader of one of the world’s largest cloud computing platforms, serving everyone from Netflix to the U.S. intelligence agencies, Garman has a front-row seat to how companies are actually using AI.

And what he is seeing makes him worried that short-term thinking could damage businesses for years to come. Garman’s point is grounded in long-term strategy. A company that relies solely on AI to handle tasks without training new talent could find itself short of people.

Still, Garman admits the next few years will be bumpy. “Y our job is going to change ,” he said. He believes AI will make companies more productive as well as the employees.

When technology makes something easier, people want more of it. AI enables the creation of software faster, allowing companies to develop more products, enter new markets, and serve more customers.

Developers will be responsible for more than just writing code, with faster adaptation to new technologies becoming essential. But he has a hopeful message in the end.

That’s why Geoffrey Hinton has advised that Computer Science degrees remain essential . This directly supports Matt Garman’s point. Fresh talent with a strong understanding of core fundamentals becomes crucial for filling these higher-value roles of the future.

I’m very confident in the medium to longer term that AI will definitely create more jobs than it removes at first, ” Garman said.

Flick (YC F25) Is Hiring Founding Engineer to Build Figma for AI Filmmaking

Hacker News
www.ycombinator.com
2025-12-17 17:00:39
Comments...
Original Article

Figma + Cursor, for AI Filmmaking

Founding Frontend Engineer

$100K - $200K 0.10% - 1.00% Sunnyvale, CA, US / Remote

Role

Engineering, Frontend

Connect directly with founders of the best YC-funded startups.

Apply to role ›

About the role

About Us

Flick is defining the future interface for AI native filmmaking. Think Figma and Cursor, but for creating AI films.

  • Founded by Engineer who built Instagram Stories + Award winning filmmaker, we are a team of Tech + Artist.
  • Well-funded by top VCs.
  • Checkout our launch video
  • Award-winning AI film created using Flick
  • People talk about us on social

The Role

As our founding front-end engineer, you’ll lead the development of the core experience of Flick — our canvas, timeline, and creative tooling. You will work directly with the founders, and have the opportunity to shape the future interface for AI visual storytelling.

What you’ll do

  • Lead the architecture and development of our editor UI from the ground up (canvas, timeline, node graph, playback).
  • Rapidly prototype and iterate on new creative workflows to validate ideas and user experience.
  • Establish best practices for code quality, performance, testing, and maintainability.
  • Collaborate closely with design, product, and AI backend teams to shape the end-to-end user experience.
  • Drive key technical and product decisions as part of the founding engineering team.

Requirements

  • Experience owning and leading technical initiatives on high-performance web applications.
  • Strong expertise with modern front-end tooling (React, TypeScript, build systems, CI/CD).
  • Deep experience optimizing complex UX interactions , especially in editors, canvases, visual builders, or multimedia tools.
  • Ability to design scalable UI architectures and manage large, dynamic client-side state.
  • A passion for creating fast, intuitive, and beautiful creative interfaces.
  • Startup mindset: you thrive in fast-moving environments, take ownership, and solve ambiguous problems at scale.

Nice-to-have

  • Experience with video editors, creative canvas, animation/keyframe systems, design tools, node-graph editors, or similar.
  • Love films and art.
  • Have contributed in open-source projects, and coding for fun outside of regular work.

About Flick

Flick is defining the future interface for AI native filmmaking. Think Figma and Cursor, but for creating AI films.

  • Founded by Engineer who built Instagram Stories + Award winning filmmaker, we are a team of Tech + Artist.
  • Well-funded by top VCs.
  • Checkout our launch video
  • Award-winning AI film created using Flick
  • People talk about us on social

Flick

Founded: 2025

Batch: F25

Team Size: 2

Status: Active

Founders

Firefox is becoming an AI browser and the internet is not at all happy about it

Hacker News
www.pcgamer.com
2025-12-17 17:00:12
Comments...
Original Article

There's no such thing as bad publicity, they say. Mozilla must be clinging to that aphorism for dear life right now, what with the internet meltdown that met its announcement that Firefox is to become an AI browser over the next three years.

Mozilla's new CEO, Anthony Enzor-DeMeo, is putting AI up front and centre. "Firefox will remain our anchor. It will evolve into a modern AI browser and support a portfolio of new and trusted software additions," he says.

In mitigation, Enzor-DeMeo also says that the AI element in Firefox will be optional. "First: Every product we build must give people agency in how it works. Privacy, data use, and AI must be clear and understandable. Controls must be simple. AI should always be a choice — something people can easily turn off," Enzor-DeMeo explains.

While Mozilla says that the transition to AI will be a three-year process, it's also clear that they don't plan to hang about. "We will move with urgency. AI is changing software. Browsers are becoming the control point for digital life. Regulation is shifting defaults. These shifts play to Mozilla’s strengths," Enzor-DeMeo goes on.

Chrome with Gemini

Google has rolled out Gemini for Chrome in the US already... (Image credit: Google)

Over on X, it's a similar story, with one user commenting (via Windows Central ), "I've never seen a company so astoundingly out of touch with the people who want to use its software."

Keep up to date with the most important stories and the best deals, as picked by the PC Gamer team.

Mozilla's new CEO obviously doesn't agree. "Firefox will reach new audiences," he says, "our portfolio will strengthen our independence. Our approach to building trusted software will set a high standard for the industry."

Personally, I can see both sides of this. Admittedly, my heart sinks at the mere mention of AI, of late. But can the likes of Mozilla totally sit the AI revolution out? That seems unlikely.

Perhaps the role organisations like Mozilla can play is to implement AI in more considered, controlled way, instead of spewing it everywhere in a crazed hope to cash in. For now, then, the jury should surely be out on this move. Let's wait and see exactly how Mozilla plays AI, no?

AMD Ryzen 9 9800X3D processor

Critical React2Shell flaw exploited in ransomware attacks

Bleeping Computer
www.bleepingcomputer.com
2025-12-17 16:09:51
A ransomware gang exploited the critical React2Shell vulnerability (CVE-2025-55182) to gain initial access to corporate networks and deployed the file-encrypting malware less than a minute later. [...]...
Original Article

Critical React2Shell flaw exploited in ransomware attacks

A ransomware gang exploited the critical React2Shell vulnerability (CVE-2025-55182) to gain initial access to corporate networks and deployed the file-encrypting malware less than a minute later.

React2Shell is an insecure deserialization issue in the React Server Components (RSC) 'Flight' protocol used by the React library and the Next.js framework. It can be exploited remotely without authentication to execute  JavaScript code in the server's context.

Within hours of its disclosure, nation-state hackers started to exploit it in cyberespionage operations or to deploy new EtherRAT malware . Cybercriminals were also quick to leverage it in cryptocurrency mining attacks.

Wiz

However, researchers at corporate intelligence and cybersecurity company S-RM observed React2Shell being used in an attack on December 5 by a threat actor that deployed the Weaxor ransomware strain.

Weaxor ransomware attack

Weaxor ransomware appeared in late 2024 and is believed to be a rebrand of the Mallox/FARGO operation (also known as 'TargetCompany') that focused on compromising MS-SQL servers .

Like Mallox, Weaxor is a less sophisticated operation that targets public-facing servers with opportunistic attacks demanding relatively low ransoms.

The operation does not have a data leak portal for double extortion, and there’s no indication that it performs data exfiltration before the encryption phase.

S-RM researchers say that the threat actor deployed the encryptor shortly after gaining initial access through React2Shell. While this suggests an automated attack, the researchers did not find any evidence in the compromised environment to support the theory.

Immediately after the breach, the hackers executed an obfuscated PowerShell command that deployed a Cobalt Strike beacon for command and control (C2) communication.

In the next step, the attacker disabled real-time protection in Windows Defender and launched the ransomware payload. All this happened in less than a minute since the initial access stage.

According to the researchers, the attack was limited to the endpoint that was vulnerable to React2Shell, as they did not observe any lateral movement activity.

After encryption, the files had the '.WEAX' extension, and every impacted directory had a ransom note file named 'RECOVERY INFORMATION.txt', which contained payment instructions from the attacker.

S-RM says that Weaxor also wiped volume shadow copies to prevent easy restoration and cleared event logs to make forensic analysis more difficult.

Notably, the researchers report that the same host was subsequently compromised by other attackers using different payloads, which is indicative of the level of malicious activity around React2Shell.

S-RM suggests that system administrators review Windows event logs and EDR telemetry for any evidence of process creation from binaries related to Node or React, as patching alone isn’t enough.

Process spawning of cmd.exe or powershell.exe from node.exe is a strong indicator of React2Shell exploitation Unusual outbound connections, disabled security solutions, log clearing, and resource spikes should also be thoroughly investigated.

tines

Break down IAM silos like Bitpanda, KnowBe4, and PathAI

Broken IAM isn't just an IT problem - the impact ripples across your whole business.

This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

What Does a Database for SSDs Look Like?

Lobsters
brooker.co.za
2025-12-17 16:09:19
Comments...
Original Article

Maybe not what you think.

Over on X, Ben Dicken asked :

What does a relational database designed specifically for local SSDs look like? Postgres, MySQL, SQLite and many others were invented in the 90s and 00s, the era of spinning disks. A local NVMe SSD has ~1000x improvement in both throughput and latency. Design decisions like write-ahead logs, large page sizes, and buffering table writes in bulk were built around disks where I/O was SLOW, and where sequential I/O was order(s)-of-magnitude faster than random. If we had to throw these databases away and begin from scratch in 2025, what would change and what would remain?

How might we tackle this question quantitatively for the modern transaction-orientated database?

But first, the bigger picture. It’s not only SSDs that have come along since databases like Postgres were first designed. We also have the cloud, with deployments to excellent datacenter infrastructure, including multiple independent datacenters with great network connectivity between them, available to all. Datacenter networks offer 1000x (or more) increased throughput, along with latency in the microseconds. Servers with hundreds of cores and thousands of gigabytes of RAM are mainstream.

Applications have changed too. Companies are global, businesses are 24/7. Down time is expensive, and that expense can be measured. The security and compliance environment is much more demanding. Builders want to deploy in seconds, not days.

Approach One: The Five Minute Rule

Perhaps my single favorite systems paper, The 5 Minute Rule… by Jim Gray and Franco Putzolu gives us a very simple way to answer one of the most important questions in systems: how big should caches be? The five minute rule is that, back in 1986, if you expected to read a page again within five minutes you should keep in in RAM. If not, you should keep it on disk. The basic logic is that you look at the page that’s least likely to be re-used. If it’s cheaper to keep around until it’s next expected re-use, then you should keep more. If it’s cheaper to reload from storage than keep around, then you should keep less 1 . Let’s update the numbers for 2025, assuming that pages are around 32kB 2 (this becomes important later).

The EC2 i8g.48xlarge delivers about 1.8 million read iops of this size, at a price of around $0.004576 per second, or \(10^{-9}\) dollars per transfer (assuming we’re allocating about 40% of the instance price to storage). About one dollar per billion reads. It also has enough RAM for about 50 million pages of this size, costing around \(3 \times 10^{-11}\) dollars to storage a page for one second.

So, on this instance type, we should size our RAM cache to store pages for about 30 seconds. Not too different from Gray and Putzolu’s result 40 years ago!

That’s answer number one: the database should have a cache sized so that the hot set contains pages expected to be accessed in the next 30 seconds, for optimal cost. For optimal latency, however, the cache may want to be considerably bigger.

Approach Two: The Throughput/IOPS Breakeven Point

The next question is what size accesses we want to send to our storage devices to take best advantage of their performance. In the days of spinning media, the answer to this was surprisingly big: a 100MB/s disk could generally do around 100 seeks a second, so if your transfers were less than around 1MB you were walking away from throughput. Give or take a factor of 2. What does it look like for modern SSDs?

SSDs are much faster on both throughput and iops. They’re less sensitive than spinning drives to workload patterns, but read/write ratios and the fullness of the drives still matter. Absent benchmarking on the actual hardware with the real workload, my rule of thumb is that SSDs are throughput limited for transfers bigger than 32kB, and iops limited for transfers smaller than 32kB.

Making transfers bigger than 32kB doesn’t help throughput much, reduces IOPS, and probably makes the cache less effective because of false sharing and related effects. This is especially important for workloads with poor spatial locality .

So that’s answer number two: we want our transfers to disk not to be much smaller than 32kB on average, or we’re walking away from throughput.

Approach Three: Durability and Replication

Building reads on local SSDs is great: tons of throughput, tons of iops. Writes on local SSDs, on the other hand, have the distinct problem of only being durable on the local box, which is unacceptable for most workloads. Modern hardware is very reliable, but thinking through the business risks of losing data on failover isn’t very fun at all, so let’s assume that our modern database is going to replicate off-box, making at least one more synchronous copy. Ideally in a different availability zone (AZ).

That i8g.48xlarge we were using for our comparison earlier has 100Gb/s (or around 12GB/s) of network bandwidth. That puts a cap on how much write throughput we can have for a single-leader database. Cross-AZ latency in EC2 varies from a couple hundred microseconds to a millisecond or two, which puts a minimum on our commit latency.

That gives us answer number three: we want to incur cross-AZ latency only at commit time, and not during writes.

Which is where we run into one of my favorite topics: isolation. The I in ACID . A modern database design will avoid read-time coordination using multiversioning, but to offer isolation stronger than READ COMMITTED will need to coordinate either on each write or at commit time. It can do that like, say, Aurora Postgres does, having a single leader at a time running in a single AZ. This means great latency for clients in that zone, and higher latency for clients in different AZs. Given that most applications are hosted in multiple AZs, this can add up for latency-sensitive applications which makes a lot of round trips to the database. The alternative approach is the one Aurora DSQL takes, doing the cross-AZ round trip only at COMMIT time, saving round-trips.

Here’s me talking about the shape of that trade-off at re:Invent this year:

There’s no clear answer here, because there are real trade-offs between the two approaches. But do make sure to ask your database vendor whether those impressive latency benchmarks are running where you application actually runs. In the spirit of the original question, though, the incredible bandwidth and latency availability in modern datacenter networks is as transformative as SSDs in database designs. Or should be.

While we’re incurring the latency cost of synchronous replication, we may as well get strongly consistent scale-out reads for free. In DSQL, we do this using high-quality hardware clocks that you can use too . Another nice win from modern hardware. There are other approaches too.

That’s answer number four for me: The modern database uses high-quality clocks and knowledge of actual application architectures to optimize for real-world performance (like latency in multiple availability zones or regions) without compromising on strong consistency.

Approach Four: What about that WAL?

Design decisions like write-ahead logs, large page sizes, and buffering table writes in bulk were built around disks where I/O was SLOW, and where sequential I/O was order(s)-of-magnitude faster than random.

WALs, and related low-level logging details, are critical for database systems that care deeply about durability on a single system. But the modern database isn’t like that: it doesn’t depend on commit-to-disk on a single system for its durability story. Commit-to-disk on a single system is both unnecessary (because we can replicate across storage on multiple systems) and inadequate (because we don’t want to lose writes even if a single system fails).

That’s answer number five: the modern database commits transactions to a distributed log, which provides multi-machine multi-AZ durability, and might provide other services like atomicity. Recovery is a replay from the distributed log, on any one of a number of peer replicas.

What About Data Structures?

B-Trees versus LSM-trees vs B-Tree variants versus LSM variants versus other data structures are trade-offs that have a lot to do with access patterns and workload patterns. Picking a winner would be a whole series of blog posts, so I’m going to chicken out and say its complicated .

Conclusion

If we had to throw these databases away and begin from scratch in 2025, what would change and what would remain?

I’d keep the relational model, atomicity, isolation (but would probably pick SNAPSHOT as a default), strong consistency, SQL, interactive transactions, and the other core design decisions of relational databases. But I’d move durability, read and write scale, and high availability into being distributed rather than single system concerns. I think that helps with performance and cost, while making these properties easier to achieve. I’d mostly toss out local durability and recovery, and all the huge history of optimizations and data structures around that 3 , in favor of getting better properties in the distributed setting. I’d pay more attention to internal strong isolation (in the security sense) between clients and workloads. I’d size caches for a working set of between 30 seconds and 5 minutes of accesses. I’d optimize for read transfers around that 32kB sweet spot from local SSD, and the around 8kB sweet spot for networks.

Probably more stuff too, but this is long enough as-is.

Other topics worth covering include avoiding copies on IO, co-design with virtualization (e.g. see our Aurora Serverless paper ), trade-offs of batching, how the relative performance of different isolation levels changes, what promises to give clients, encryption and authorization of data at rest and in motion, dealing with very hot single items, new workloads like vector, verifiable replication journals, handing off changes to analytics systems, access control, multi-tenancy, forking and merging, and even locales.

Footnotes

  1. The reasoning is slightly smarter, thinking about the marginal page and marginal cost of memory, but this simplification works for our purposes here. The marginal cost of memory is particularly interesting in a provisioned system, because it varies between zero (you’ve paid for it already) and huge (you need a bigger instance size). One of the really nice things about serverless (like DSQL) and dynamic scaling (like Aurora Serverless) is that it makes the marginal cost constant, greatly simplifying the task of reasoning about cache size.
  2. Yes, I know that pages are typically 4kB or 2MB, but bear with me here.
  3. Sorry ARIES .

Asahi Linux 6.18 progress report

Linux Weekly News
lwn.net
2025-12-17 16:07:13
The Asahi Linux project has published its progress report following the release of Linux 6.18. This time around the project reports progress on many fronts, including microphone support for M2 Pro/Max MacBooks, work queued for Linux 6.19 to support USB3 via the USB-C ports, and work to improve the A...
Original Article

The Asahi Linux project has published its progress report following the release of Linux 6.18. This time around the project reports progress on many fronts, including microphone support for M2 Pro/Max MacBooks, work queued for Linux 6.19 to support USB3 via the USB-C ports, and work to improve the Asahi Linux installation experience. The project is also enabling as additional System Management Controller (SMC) drivers, which means that " the myriad voltage, current, temperature and power sensors controlled by the SMC will be readable using the standard hwmon interfaces ".



loro-extended: A toolkit for building local-first applications and multi-agent systems with Loro

Lobsters
github.com
2025-12-17 15:45:21
Comments...
Original Article

Loro Extended

A toolkit for building local-first applications and multi-agent systems with Loro .

@loro-extended adds a pleasant layer of abstraction--schemas, network synchronization, persistence, and reactivity--to a raw CRDT engine called Loro. It's built to make it easy to focus on distributed application logic, instead of the usual shuttling of state between peers, clients, agents, etc. in a distributed system.


📚 Examples

Explore these example applications to see @loro-extended in action:

Todo App

Real-time collaborative todo list with React and SSE. Demonstrates offline-first architecture with automatic conflict resolution.

Todo App Screenshot

Chat with AI

Collaborative chat with AI streaming. Features reactive server-side AI responses that stream directly into Loro Text containers.

Chat App Screenshot

Video Conference

WebRTC-based video conferencing with peer-to-peer sync. Demonstrates dual-adapter architecture (SSE + WebRTC) for resilient, low-latency collaboration.

Video Conference Screenshot

Bumper Cars

Multiplayer bumper cars arena with server-authoritative physics. Demonstrates presence system for real-time game state and CRDT counters for persistent scoring.

Bumper Cars Screenshot

Hono Counter

A simple counter app using Hono's jsx-dom with Vite. Shows how to integrate @loro-extended/hono with the Hono framework.

Hono Counter Screenshot

Additional Examples:

Example Description
todo-websocket Same as todo , but uses WebSocket instead of SSE for real-time communication.
postgres Demonstrates PostgreSQL storage adapter usage. Shows how to persist Loro documents to a PostgreSQL database.

The "Zero-Plumbing" Philosophy

Whether you are building a web app or a group of cooperating AI agents, managing state synchronization is often the hardest part. You spend half your time writing "plumbing": API endpoints, WebSocket handlers, retry logic, and conflict resolution.

We think there's a better way.

Instead of treating state as something you fetch and save , treat it as something you have . You mutate local data, and the system handles the rest—persisting it, syncing it, and merging it.


Use Case 1: Modern Web Development

For web developers, @loro-extended offers a "Local-First" architecture that simplifies your stack while improving user experience.

The Problem: API Fatigue

In a traditional app, a simple "Add Todo" feature requires:

  1. Optimistic UI update code.
  2. A POST /api/todos endpoint.
  3. Database schema and migration.
  4. WebSocket logic to broadcast the change.
  5. Client-side logic to merge incoming updates.

The Solution: Mutation Sync

With @loro-extended , the process is:

  1. You write: doc.todos.push(newTodo)
  2. Done.

The library (optionally) persists the change to IndexedDB for offline support, queues it, and syncs it with peers or servers automatically. You get:

  • Real-time Collaboration: Multiplayer is default, not a feature add-on.
  • Offline Capability: Apps work perfectly without internet and sync when back online.
  • Instant Load: No loading spinners; data is available immediately from local storage.

Use Case 2: Agentic Cooperation

For AI engineers, @loro-extended provides a shared memory substrate for multi-agent systems.

The Problem: Context & Coordination

Agents often need "full context" to make good decisions--chat history, current world state, and user intent.

  • Stateless Agents suffer from amnesia or require massive context windows re-sent with every request.
  • Database-Backed Agents are slow, constantly polling or fetching state, leading to race conditions when multiple agents (or users) act simultaneously.

The Solution: Shared CRDT Memory

By treating agents as "peers" in a CRDT network, you decouple Execution (the LLM) from State (the Memory).

  • Agents as Observers: An agent can subscribe to a document. When a user (or another agent) changes the state, the agent is notified immediately with the precise delta.
  • Concurrent Action: Multiple agents can work on the same task--one generating code, another fixing bugs, a third updating the UI--without locking the state or overwriting each other.
  • Resilience: If an agent process crashes, the state is safe. Another agent can pick up exactly where it left off, because the state lives in the CRDT, not the agent's memory.

Why Loro Extended?

1. Schema-First & Type-Safe

Raw CRDTs can feel like "schemaless JSON soup." We bring structure back. Define a Shape , and get full TypeScript inference for every mutation.

import { createTypedDoc, Shape, change } from "@loro-extended/change";

// Define your schema once
const schema = Shape.doc({
  todos: Shape.list(
    Shape.struct({
      text: Shape.text(),
      done: Shape.plain.boolean(),
    })
  ),
});

const doc = createTypedDoc(schema);

// Get full intellisense and type checking
change(doc, (draft) => {
  draft.todos.push({ text: "Buy milk", done: false }); // ✅ Type-safe
  draft.todos.push({ text: 123 }); // ❌ Error: Type 'number' is not assignable to 'string'
});

2. Instant Load (No Spinners)

With our Empty State Overlay , your app renders immediately with default values while the real data syncs in the background.

  • Before: if (!data) return <Spinner />
  • After: return <div>{doc.title}</div> (Renders "Untitled" immediately, then updates)

3. Performance

Built on Loro , which is written in Rust. It is incredibly fast at merging and calculating diffs, capable of handling large documents and long editing sessions that slow other libraries down. In addition, it supports shallow snapshots and redaction , so you aren't tied to the entire document history forever.


The Stack

This monorepo is a collection of packages designed to work together:

Core Packages

Package Description
@loro-extended/change The Data Layer. A schema-driven wrapper for Loro. Provides the change() function and TypeScript magic.
@loro-extended/repo The Sync Engine. Manages documents lifecycle, storage, and network sync. It's your local data store.
@loro-extended/react The UI Layer. React hooks like useDocument and usePresence that bind your data to your views. See todo-sse , chat , and video-conference for examples.
@loro-extended/hono The UI Layer. Hono JSX hooks and utilities, including useDocument and usePresence . See hono-counter for an example.

Storage Adapters

Package Description
@loro-extended/adapter-indexeddb IndexedDB storage for browser-based persistence.
@loro-extended/adapter-leveldb LevelDB storage for server-side persistence.
@loro-extended/adapter-postgres PostgreSQL storage for server-side persistence. See postgres for an example.

Network Adapters

Package Description
@loro-extended/adapter-http-polling HTTP polling network adapter with long-polling support. See examples/todo-sse/POLLING.md for usage.
@loro-extended/adapter-sse Server-Sent Events (SSE) for real-time client-server sync. See todo-sse and chat for examples.
@loro-extended/adapter-websocket WebSocket adapter for real-time client-server sync. See todo-websocket for a full example.
@loro-extended/adapter-webrtc WebRTC data channel adapter for peer-to-peer document synchronization. See video-conference for an example.

🚀 Quick Start

Here is a complete collaborative "Counter" app in React.

import { useDocument, Shape } from "@loro-extended/react";

// 1. Define Schema (with placeholder defaults)
const counterSchema = Shape.doc({
  count: Shape.counter(),
  users: Shape.list(Shape.plain.string()),
});

function App() {
  // 2. Use the hook (Auto-syncs, Auto-persists)
  // Returns [value, changeDoc, handle] - value has placeholder defaults applied
  const [doc, changeDoc] = useDocument("global-counter", counterSchema);

  return (
    <div>
      <h1>Count: {doc.count}</h1>

      <button onClick={() => changeDoc((d) => d.count.increment(1))}>+1</button>

      <button onClick={() => changeDoc((d) => d.users.push("New User"))}>
        Join
      </button>

      <pre>{JSON.stringify(doc.users, null, 2)}</pre>
    </div>
  );
}

Setting up the RepoProvider

To make the useDocument hook work, you need to wrap your application in a RepoProvider . This is where you configure your network and storage adapters.

import { RepoProvider } from "@loro-extended/react";
import { SseClientNetworkAdapter } from "@loro-extended/adapter-sse/client";
import { IndexedDBStorageAdapter } from "@loro-extended/adapter-indexeddb";

// 1. Create your adapters
const network = new SseClientNetworkAdapter({
  postUrl: "/sync/post",
  eventSourceUrl: (peerId) => `/sync/events?peerId=${peerId}`,
});
const storage = new IndexedDBStorageAdapter();

// 2. Configure the Repo
const config = {
  adapters: [network, storage],
  identity: { name: "user-123" }, // Optional: Identify this peer
};

// 3. Wrap your app
function Root() {
  return (
    <RepoProvider config={config}>
      <App />
    </RepoProvider>
  );
}

Setting up the Server

To enable real-time sync between users, you need a simple server. We provide an Express middleware that handles the synchronization protocol.

import express from "express";
import { Repo } from "@loro-extended/repo";
import {
  SseServerNetworkAdapter,
  createSseExpressRouter,
} from "@loro-extended/adapter-sse/server";
import { LevelDBStorageAdapter } from "@loro-extended/adapter-leveldb/server";

const app = express();

// 1. Create adapters
const network = new SseServerNetworkAdapter();
const storage = new LevelDBStorageAdapter("./db");

// 2. Create the Repo (binds network <-> storage)
new Repo({
  adapters: [network, storage],
  identity: { name: "server" },
});

// 3. Mount the sync endpoints
app.use("/sync", createSseExpressRouter(network));

app.listen(3000);

Architecture

We use the Elm Architecture (TEA) pattern for our synchronization engine's state machine, ensuring predictable state transitions even in complex network conditions.

What is Loro?

Loro is the high-performance CRDT library that powers this stack. It is written in Rust and provides the core mathematical guarantees that allow concurrent editing without conflicts.

While Loro provides the engine (the CRDTs themselves), @loro-extended provides the car (the application framework).

  • Loro gives you: LoroMap , LoroList , LoroText , and the merging algorithms.
  • Loro Extended gives you: Schemas, React Hooks, Network Sync, and Persistence.

License

MIT

Maintaining an open source software during Hacktoberfest

Lobsters
crocidb.com
2025-12-17 15:33:24
Comments...
Original Article

I was finalizing the first working version of bulletty when I realized it was close to Hacktoberfest , the event created by DigitalOcean where they give t-shirts for people who contribute to open source software (more specifically, when you complete 6 successful PRs during the month of October). So I thought it could be interesting to have people contribute and help me make the feed reader better, also bringing more visibility to the project.

I started by organizing the Issues in the project: one for each feature from the project roadmap and for bugs, with many details and images. Then I added appropriate tags, such as “Improvements”, “Bugs”, “Good First Issue”, and of course the “Hacktoberfest” tag. I also wrote a pretty generic CONTRIBUTING file, mostly explaining how to proceed when suggesting changes, reporting bugs or submitting a PR.

To make it public, a few days before October, I posted on my personal accounts on X, Bluesky and Mastodon, then posted on the /r/hacktoberfest subreddit. Then I figured out there’s an official Hacktoberfest discord server with a channel for people to recruit contributors, so I did it too. I tried Hacker News, but honestly was the channel where I got the fewest views.

In just a few days, I saw the star counter on GitHub go to almost a hundred. Got many replies on all the platforms and I considered it an absolute success. Then October started…

On the very first day, I started getting multiple comments on issues of people asking me to assign the issue to them. Without any type of discussion first:

People asking to be assigned to Issues

People asking to be assigned to Issues

I thought that was a bit too quick and I realized that I didn’t want to assign issues to people without discussing what they’re planning to implement in the first place. Maybe if someone already came with a pull request, I could consider their implementation and would review the code and discuss if that’s the best way. But just assign them the issue and wait for whatever they came up with felt a bit too risky, because that meant that other people would not even check on that issue if someone is already on it.

So I updated the CONTRIBUTING file with some more information on how to work on the issues:

Working on Issues

First requirement: use the program. I’ve seen people wanting to contribute without using it. Issues will only be assigned to users when enough discussion about their implementation has taken place. It’s important that nobody keeps an issue assigned without making progress, as this prevents others from contributing. So, if you want to write code for an existing issue, start by discussing the issue and your proposed solution first.

I do think it’s fine if you submit a PR for a bugfix you made without prior discussion, as long as you take the time to explain the why and the how. In that case, the issue won’t be assigned to you until the merge is complete.

So I replied that user:

I have a knowledge!

I have a knowledge!

I instantly suspected the user would be vibe-coding due to the way they described their proposal for the issue. So I asked, and they confirmed some sort of vibe-coding workflow. So I had to go and update the CONTRIBUTING file once again:

Generative AI use

I don’t want to go as far as prohibiting anyone from using AI. After all, at this point, some AI use is inevitable. However, purely vibe-coded PRs are not going to be approved. If you’re using AI to generate code, you must make it very clear. And you’ll have to own it and maintain it. I will review and ask as many questions as necessary about the code, and I reserve the right to judge whether I think the contribution is worth it or not.

Also, not properly communicating that you’re using generated code in your PR is considered dishonest. If I find out, I’ll have to close the PR.

I use some AI myself, it’s not the problem. However I see people simply delegating to an LLM to write all the code for them, and I think it’s just bad.

That user eventually submitted a PR for that:

Looks too detailed explanation for an implementation that didn’t even build

Looks too detailed explanation for an implementation that didn’t even build

The PR didn’t even build; the code wasn’t formatted (despite me explicitly saying it’s important in the CONTRIBUTING file); the two commits were titled “Update readerscreen.rs” , without any logical division; there was even an instance of a method’s name that was changed, but without changing the name in the Trait it inherited from:

handle_events was changed to handle_event for no apparent reason

handle_events was changed to handle_event for no apparent reason

So many indications that the user just asked their own agentic copilot for the changes and just tried to submit the PR. I closed the issue with some harsh words, something like “please avoid wasting both our times”.


Some of the issues got people adding “attack plans” that looked very clearly LLM-generated, because they didn’t make much sense to begin with. For example, one of the issues is caching the feed library, something that needs to be done but can be as simple as keeping a local variable of the feed entries per feed source, instead of querying the disk on every interaction (which is still happening to this day). One user suggested very vague and nonsensical cache infrastructure right after affirming they were not vibe-coding:

interesting cache infrastructure

interesting cache infrastructure

I remember reading from other maintainers that during Hacktoberfest, it was really common to get spammy PRs with mostly typo fixing, simple comments being added or removed, or plainly useless changes. Now, with AI coding and advanced agentic models where you just show your codebase and ask for modifications and it does it all in place, maintaining open source software is getting more complex. For simple tasks, it might not even be a problem, but I can see users contributing with big refactors that were completely machine-made, possibly introducing not only a series of bugs, but eventually creating a code that nobody fully understands. Simply because LLMs have no “theory” , as in Peter Naur’s “Programming as Theory Building” .

Plus, everyone seems to have their own conviction on what has been created with AI or not. This whole post is about how I dealt with possible AI generated contribution mostly based on the behaviour and messages of the user proposing them. But these could be just mistakes, maybe they were really just made by humans. For example, I see some people judging texts that are overly formatted with italics, bold and underline as something that LLMs could have done, but I myself do it quite a lot since forever. AI could be creating noise in the open source software community.

There were good contributions

Nevertheless, there were good contributions. After the first wave of weird PRs, some more well-intentioned people got interested and started contributing to the project. Highlight to these PRs:

Add next/prev navigation to the reader

A very important feature that was missing, the ability to navigate previous/next posts from the reader screen itself. The implementation taught me about Rc<RefCell<>> in Rust.

Feature: Read Later

The ability to store articles in a separate category to be read later. This was an extremely nice PR made by alfaarghya , after some very nice discussion on the best ways to implement it. He also contributed with other nice PRs during the time.


Some other PRs that I’ve reviewed and merged into the project were:

These inspired me so much that I ended up implementing many features during this time too. Since I was submitting PRs for myself to approve too, Hacktoberfest considered these and also sent me a t-shirt (that hasn’t arrived yet).


In the end it was a good idea. bulletty got some visibility, code contributions, many people also posting bugs and suggestions, even after the event. The project has now 250 stars on GitHub:

The best LED face masks in the UK, tested: 10 light therapy devices that are worth the hype

Guardian
www.theguardian.com
2025-12-17 15:09:45
They claim to fix fine lines, blemishes and redness – but which stand up to scrutiny? We asked dermatologists and put them to the test to find out • The best anti-ageing creams, serums and treatments LED face masks are booming in popularity – despite being one of the most expensive at-home beauty pr...
Original Article

L ED face masks are booming in popularity – despite being one of the most expensive at-home beauty products ever to hit the market. Many masks are available, each claiming to either reduce the appearance of fine lines, stop spots or calm redness. Some even combine different types of light to enhance the benefits.

But it’s wise to be sceptical about new treatments that are costly and non-invasive, and to do your research before you buy. With this in mind, I spoke with doctors and dermatologists to find out whether these light therapy devices actually work.

They’re not a miracle cure for deep-set wrinkles, but experts say the best light therapy masks can promote collagen production, improve elasticity and help smooth skin with sustained use. And while it might seem like a new technology, research dating back to the 90s shows the efficacy of light therapy in wound healing, acne treatment and skin rejuvenation.

Red and infrared light are safe to use on all skin types, but be warned that blue light can worsen hyperpigmentation on darker skin tones.

I’ve tested some of the most popular devices on the market – including infrared masks – to narrow down my favourite LED face masks for treating a range of skin concerns.


At a glance

  • Best LED face mask overall:
    CurrentBody Series 2

£399.99 at CurrentBody
  • Best budget LED face mask:
    Silk’n LED face mask 100

£99.99 at Lookfantastic
  • Best for targeting multiple skin concerns:
    Shark CryoGlow

£299 at John Lewis
  • Best LED device for acne-prone skin:
    Lustre ClearSkin Solo

£50.40 at Amazon
  • Best LED mask for treating multiple areas:
    StylPro Wavelength Pro 5-in-1

£249 at Lookfantastic

Why you should trust me

I’ve been reviewing health and beauty tech for the past four years. During this time I’ve witnessed many beauty fads come and go. Naturally tight-fisted and a bit of a sceptic, I was initially struck by the cost of these masks. How on earth can an elaborate LED light strip set you back over £300?

But after testing multiple light therapy masks, I’ve come to understand the technology behind them, and sadly you won’t be able to engineer your own light therapy system with a costume mask and a set of LED string lights.

I don’t have many fine lines or wrinkles to test on, but I can comment on how blue light treatment affects acne because I’ve suffered from it since I was a teenager – despite my mum’s assurances that it would clear up after puberty. The experts I spoke to agreed on the efficacy of red and infrared light for anti-ageing.


Are LED face masks actually worth it?

Light therapy masks are fantastic additions to a skincare routine, helping to smooth, firm and reduce blemishes. Since I started using one almost a year ago, my skin is calmer, less prone to redness, and has a more even tone.

However, LED masks can be expensive, and if you’re not disciplined enough to use one regularly, you won’t see results. Before you jump in and splash between £100 and £400, keep in mind that light therapy masks are most effective when paired with a good skincare routine. It’s crucial to make sure skin is properly cleansed before treatment and protected from sun damage afterwards.

If you don’t already have a skincare routine nailed down, don’t buy a light therapy mask just yet. Consider starting out using a gentle cleanser and moisturiser, with an SPF for daytime. You could also incorporate targeted skincare serums, such as retinol and vitamin C , to help firm and brighten the skin without the need for an expensive light therapy mask.


How I tested

The writer in a mirror wearing the Shark Cryoglow mask with blue light glowing underneath.
‘I tested the fit, comfort levels and usability of 13 of the most popular light therapy masks.’ Photograph: Sarah Matthews/The Guardian

Since LED treatments take a while to show visible results, it’s difficult to test multiple light therapy masks at once (at least, without spending a few years testing them), so I enlisted the help of dermatologists who were familiar with light therapy treatments long before they were commercially available.

I spoke with Dr Barbara Kubicka, an expert in aesthetic medicine; Dr Derrick Phillips, a consultant dermatologist and spokesperson for the British Skin Foundation; and aesthetic doctor Dr Priya Verma, an authority on the science of skin ageing.

I asked the experts to identify which features of a light therapy mask – such as bulb quality and quantity, light wavelength and treatment time – matter the most, to inform my choices. They also outlined the suitability of light therapy for different skin types and its associated risks.

Armed with their advice, I tested the fit, comfort levels and usability of 13 of the most popular light therapy masks and other targeted LED devices. Getting hands on with the masks allowed me to pinpoint any of the key features the experts recommended, as well as useful features I found helpful as a consumer.

I’ve been using a light therapy mask regularly for the past 12 months, so I can identify a good mask from a bad one. My tests also included monitoring how well the treatments worked after four nightly sessions, with the obvious caveat that only very minimal results could be observed after such a short-term treatment. I then tested my favourite masks over several months, too, helping me to verify any unique treatment claims – as well as giving me plenty of opportunities to scare my boyfriend by sneaking up on him wearing each one.

Only masks that use the brightest, flicker-free bulbs, fit comfortably and are easy to use made the final cut. After testing, I returned the masks sourced for this article to the manufacturers. Where that wasn’t possible, I cleaned the masks and donated them to the Redbridge Reach Out service, a charity that supports anyone experiencing domestic abuse.


The best LED face masks in 2025

Three masks on a table with remote and red light behind them.
Photograph: Sarah Matthews/The Guardian

Best LED face mask overall:
CurrentBody Series 2

CurrentBody

Series 2

from £399.99

What we love
Excellent facial coverage, comfortable to wear with deep near-infrared lights

What we don’t love
Only one treatment plan and no screen to display treatment time

The Currentbody Series 2 mask on a wooden table.
Photograph: Sarah Matthews/The Guardian
£399.99 at CurrentBody
£399.99 at Amazon

This is the second red light therapy mask from CurrentBody, and it’s easily the brightest and best-fitting mask I’ve tested. If you want the most powerful red light mask money can buy, I believe this is worth the cost.

The mask has 236 LED bulbs that blend red, near-infrared and deep near-infrared light, the latter of which is exclusive to the Series 2 mask. The original mask , which is £100 cheaper, has only the former two light frequencies.

The deep near-infrared lights penetrate deeper than the other two types of light, CurrentBody claims. This leads to more effective treatment where it’s needed most – the deep near-infrared bulbs are positioned under the eyes and around the lips to better target areas where ageing is more pronounced. Add surface-level red light and near-infrared light, and you’ve got a face mask that works harder than most.

Why we love it
I loved how simple the mask was to use. After attaching it to my head using the adjustable straps, I turned on the mask to activate a 10-minute treatment. It offered brilliant facial coverage, wrapping all the way under my chin. And its eye guards were highly effective, blocking any glare from the bright lights and allowing me to continue doing my daily activities – or endlessly scrolling – while wearing the mask.

I used this mask for three months, and was pleased to notice my skin tone looking calmer and more even than usual, with less undereye inflammation. As it’s a red light mask, it didn’t have much effect on my acne, but it did help to reduce redness.

If you have blemish-prone skin, CurrentBody does sell a blue light mask for the same price. It has the same comfortable, high-coverage fit and high-quality bulbs, but uses blue and red bulbs (slightly fewer: 220) to target acne-causing bacteria and reduce inflammation.

It’s a shame that … the mask offers only one treatment setting and there isn’t a screen displaying the treatment time. Neither is a dealbreaker, but it’s nice to be able to choose different treatments, and almost every other mask includes a countdown timer.

Number of LEDs: 236
Number of settings: one
Treatment time:
10mins
Light frequencies:
red (633nm), near-infrared (830nm), deep near-infrared (1,072nm)
Timer countdown: no

CurrentBody

Series 2

from £399.99

What we love
Excellent facial coverage, comfortable to wear with deep near-infrared lights

What we don’t love
Only one treatment plan and no screen to display treatment time


Best budget LED face mask:
Silk’n LED face mask 100

Silk’n

LED face mask 100

from £89.99

What we love
Comfortable to use, good colour choices, accessible price

What we don’t love
Fewer bulbs than higher-end models and no near-infrared

Silk’n light therapy mask laid flat on a table.
Photograph: Sarah Matthews/The Guardian
£99.99 at Lookfantastic
£160 at Cult Beauty

If you want to try light therapy without remortgaging the house, the Silk’n LED face mask 100 is a good choice. It has 100 LED bulbs with good facial coverage, is comfortable to wear and offers a good range of light colours. It doesn’t have near-infrared lights like the pricier options, but it covers the basics at a decent price.

Why we love it
This mask offers four colour modes: red, blue, yellow and purple. Red light helps stimulate collagen to reduce the appearance of fine lines, while blue light helps to soothe breakouts. The purple light comes from mixing the aforementioned blue and red lights, combining the effects of both to boost the skin’s overall evenness.

Although less widely researched (and with limited clinical evidence to suggest efficacy), the experts I spoke to said the yellow light treatment could help improve hydration levels in the skin. I didn’t notice a huge hydration hit when testing this feature, so if your skin is crying out for hydration, I recommend using the other light settings alongside a hydrating serum .

Each colour can be selected individually for a 10-minute targeted session, or you can select automatic mode, which cycles through the colours over 15 minutes to provide all the benefits at once.

I found the Silk’n light therapy mask simple to use and comfortable to wear. Its flexible silicone build didn’t feel quite as sturdy as more expensive options, but I didn’t really notice this when using the mask. The built-in eye shields weren’t as bulky as others, but they still blocked out the light and protected my eyes well.

The automatic mode left my skin feeling completely comfortable, with a slightly glowier finish than usual – just what I’d expect from an entry-level mask like this one.

It’s a shame that … there’s no timer and it has fewer than half the bulbs of the CurrentBody, with no near-infrared light treatment for effective collagen stimulation deeper in the skin. This means it’s better for light-touch anti-ageing, and for soothing, acne-busting blue light treatments.

Number of LEDs: 100
Number of settings:
5
Treatment time:
10 or 15mins
Light frequencies:
red (633nm), purple (463-633nm), blue (463nm), yellow (592nm)
Timer countdown:
no

Silk’n

LED face mask 100

from £89.99

What we love
Comfortable to use, good colour choices, accessible price

What we don’t love
Fewer bulbs than higher-end models and no near-infrared


Best for targeting multiple skin concerns:
Shark CryoGlow

What we love
Intuitive to use, good targeted treatments and soothing undereye cooling

What we don’t love
Heavy mask that presses into the under eyes when reclining

The reverse of the Shark Cryoglow with pink LEDs showing.
Photograph: Sarah Matthews/The Guardian
£299 at John Lewis
£299.99 at Shark

Many will be familiar with Shark’s vacuum cleaners and hair-styling gadgets, but the brand’s latest venture is in skincare. The Shark CryoGlow is the only LED face mask to offer built-in undereye cooling alongside targeted light therapy for anti-ageing and acne repair.

Why we love it
The CryoGlow offers three different wavelengths of light: blue, red and deep-infrared. It has three presets for “better ageing”, “blemish repair” and “skin sustain”. If these aren’t clear enough, the control screen explains exactly what each mode is designed to do, making it really user-friendly.

I found the lights incredibly bright during my tests – though for safety they automatically dim when you remove the mask from your face – but I was happy with how the mask shielded my eyes.

During every treatment, you can choose to switch on the cooling undereye patches, which aim to de-puff and soothe your skin. The cooling can also be used on its own, without the LEDs. There are three levels, the coolest of which felt startlingly cold at first but did a great job of calming down my eyes on a particularly bad hay fever day. Likewise, the blemish mode did a brilliant job of calming spots and redness with sustained use. I also liked using the skin sustain mode for a quick pick-me-up to brighten my skin before a night out.

As you might imagine, using the cooling feature on full blast drains the battery more quickly. I performed two battery-rundown tests on the CryoGlow without cooling, and it managed 17 treatments. With maximum cooling enabled, however, this dropped to just seven. That’s still a decent number of treatments in between charges, but it’s something to bear in mind.

It’s a shame that … since it’s made of plastic, it’s noticeably heavier than its silicone competitors. Thankfully, Shark has made the mask fit comfortably by using cushioned inserts at the forehead, brow and nose area.

That’s when you’re sitting up, at least; when lying down, the metal cooling patches pressed into the delicate area under my eyes. Another unfortunate side-effect of the cooling is the whirring noise it makes – inaudible from far away, but pretty noisy when pressed on to your face.

Number of LEDs: 160
Number of settings: four
Treatment time: 4-8mins light therapy; 5-15mins under-eye cooling
Light frequencies: red (630nm), infrared light (830nm), blue light (415nm)
Timer countdown: yes

Shark

CryoGlow

from £299

What we love
Intuitive to use, good targeted treatments and soothing undereye cooling

What we don’t love
Heavy mask that presses into the under eyes when reclining


Best LED device for acne-prone skin:
Lustre ClearSkin Solo

Lustre

ClearSkin Solo

from £50.40

What we love
Targeted blemish treatments in a portable package

What we don’t love
Leech-like appearance and extra running cost

Lustre Clearskin Pro device.
Photograph: Sarah Matthews/The Guardian
£63 at Lustre
£50.40 at Amazon

Acne can be a real pain, and many cosmetic treatments that target it leave skin feeling irritated, dry and flaky. These nifty adhesive LED patches from Lustre use blue light, which the company claims reduces acne-causing bacteria.

Why we love it
Each Solo patch has 15 pure blue LEDs at the proven wavelength for treating acne , 415nm. The patches cover a targeted area of skin about 2.5 x 5cm, which is perfect for treating problem areas such as the chin, cheeks and forehead. Since they’re rechargeable and far smaller than a typical LED face mask, they’re highly portable, making it easy to stay consistent with treatments wherever you are.

I found the targeted treatments very effective for minimising breakouts in my chin area – somewhere I often struggle with spots. My skin was also quicker to heal, with fewer breakouts, the longer I continued with treatments.

The patches come with a supply of double-sided adhesive to fix each one to your skin, allowing you to move around freely during treatment. This also means, unlike typical light therapy masks, they can be safely fixed anywhere on the body.

If you’re worried that the adhesive will feel uncomfortable or be tricky to remove from breakouts, don’t be. The patches are so lightweight that the adhesive doesn’t need to be very strong. I found it easy and comfortable to peel off the patches after the recommended 20-minute treatment time.

It’s a shame that … you need to buy the sticky patches when they run out. These cost £18 for a pack of 60 , or 30p each. They also look a bit like leeches – only you can decide if that’s more palatable than the Hannibal Lecter look of the full-face LED masks.

N umber of LEDs: 15
N umber of settings: one
Treatment time: 20mins
Light frequencies: blue (415nm)
Timer countdown: no

Lustre

ClearSkin Solo

from £50.40

What we love
Targeted blemish treatments in a portable package

What we don’t love
Leech-like appearance and extra running cost


Best LED mask for treating multiple areas:
StylPro Wavelength Pro 5-in-1

StylPro

Wavelength Pro 5-in-1

from £249

What we love
Adjustable design and versatile settings

What we don’t love
Less close contact with the chin area

The Stylpro wavelength pro-1
Photograph: Sarah Matthews/The Guardian
£249 at Lookfantastic
£249 at Amazon

The neck and decollete are often the first places to show signs of ageing, as the skin is thinner in those areas. Consequently, expensive neck light therapy masks have started to flood the market – but rather than requiring additional expensive kit, this StylPro option can be adjusted to treat multiple areas.

Whether your main concern is ageing on your face and neck or treating blemishes on your upper back, the Wavelength Pro can be used to treat it. It can also treat the scalp using red light, which research suggests can stimulate hair growth .

Why we love it
This mask is incredibly versatile. It has red, deep red, near-infrared and blue light, which all combine into 11 programs to target different areas of concern on your body. The remote control has a huge screen, making it easy to select the desired program and treatment zone. This also displays the mask’s battery life and treatment time.

In my tests, the straps did a great job of keeping the flexible silicone mask in place. Its eye shields were also brilliant at blocking out light, and the snap fasteners made it easy to adjust the mask between different treatment areas. To treat the back and neck area, I found you needed to lie down or sit up very straight to prevent it from slipping, but it was great to have the versatility.

This is also the only mask I’ve tested that has a silver reflective surface behind the LEDs, and a negative meniscus lens over each of the 137 bulbs. This crescent moon shaped lens has a sharper curve on its concave surface, which causes the light to spread out. StylPro claims this helps to enhance the light dispersion, to get more even coverage, unlike the focused treatment spots you find in other light therapy masks. I didn’t notice this making a huge difference to my results, but it didn’t hurt either.

It’s a shame that … when used in face mode, the mask hangs a few inches away from the chin area, which means the light has less direct contact there. Its eye guards also tended to gently pinch the bridge of my nose when worn.

Number of LEDs: 137
Number of settings: 11
Treatment time: 12-15mins
Light frequencies: red (633nm), deep red (655nm) near-infrared (830nm), blue (415nm)
Timer countdown: yes

StylPro

Wavelength Pro 5-in-1

from £249

What we love
Adjustable design and versatile settings

What we don’t love
Less close contact with the chin area


The best of the rest

The lustre clearskin renew pro facewear led mask illuminated pink on a wooden surface
‘You can choose which kind of light you want to use in four areas of your face’: the Lustre ClearSkin Renew Pro Facewear. Photograph: Sarah Matthews/The Guardian

Zkin light therapy mask

Zkin

Light therapy mask

£499

What we love
Intuitive controls with comfortable eye guards

What we don’t love
Its price tag and limited availability

The Zkin mask glowing red with remote held in front of the mask
Photograph: Sarah Matthews/The Guardian
£499 at Zkin

Best for: anti-blemish and anti-ageing in a flexible mask

If the Shark CryoGlow listed above tempts you but you don’t want to use the noisy cooling patches, this mask from Zkin is a brilliant alternative. You may not recognise the brand, but it’s the brainchild of medical consultant Dr Ifeoma Ejikeme.

The mask comes with the most widely researched red, blue and near-infrared light, with three modes: red, blue and combination. Whichever you choose, the mask uses near-infrared light to stimulate repair below the skin’s surface and boost circulation . Since it’s made from flexible silicone with removable eye inserts, I found it very comfortable to wear during testing.

It didn’t make the final cut because … it’s pretty expensive. You’d be better off buying the CurrentBody mask if you’re after very powerful red light treatment and coverage. It also has fewer bulbs than masks of a similar price.

N umber of LEDs: 122; number of settings: three; treatment time: 10mins; light frequencies: blue (460nm), red (630nm and 660nm), and near-infrared (850nm); timer countdown: yes

Zkin

Light therapy mask

£499

What we love
Intuitive controls with comfortable eye guards

What we don’t love
Its price tag and limited availability


Flikeze PhotonMask Quint

Flikeze

PhotonMask Quint

from £159.99

What we love
Comfortable to wear and a good range of colours

What we don’t love
No nose coverage

The writer in a mirror wearing the Flikeze mask which is black and glows red.
Photograph: Sarah Matthews/The Guardian
£179.99 at Flikeze
£159.99 at Amazon

Best for: a comfortable fit

The Flikeze light therapy mask offers a wide range of light colours: red, near-infrared, blue, green and yellow. Its settings include anti-ageing (red light), repair (yellow), brightening (green) and acne care (blue and red), and you can choose to do a 10- or 15-minute treatment. These all use near-infrared rather than deep infrared light.

The best thing about this mask is how comfortable it is. It has two straps that wrap around the top and bottom of your head, holding it to your face without the mask ever feeling weighty or digging in. Its eye shades fit like diving goggles and kept my eyes completely shaded from light during treatment (you can see how little light leakage there is in the haunting photograph from testing).

It didn’t make the final cut because … for the cost, it has fewer bulbs than average and the bulbs don’t cover the bridge of your nose – not a likely problem area for wrinkles, but spots can be a problem there. It also looks particularly disconcerting when worn.

N umber of LEDs: 92; number of settings: four; treatment time: 10-15mins; light frequencies: red (660nm), near-infrared (850nm), blue (415nm), green (532nm), yellow (590nm); timer countdown: yes

Flikeze

PhotonMask Quint

from £159.99

What we love
Comfortable to wear and a good range of colours

What we don’t love
No nose coverage


Lustre ClearSkin Renew Pro Facewear

Lustre

ClearSkin Renew Pro Facewear

from £224.99

What we love
App control for personalised treatments

What we don’t love
Less comfortable to wear

Lustre Clearskin Renew Pro Facewear mask face up on a table
Photograph: Sarah Matthews/The Guardian
£224.99 at Boots
£225 at Lustre

Best for: wireless controls and customised treatment

Most light treatment masks have wired controls. That doesn’t mean you need to remain tethered to a single spot, but it does mean there’s a remote that you have to carry around with you. This mask from Lustre, on the other hand, is controlled via a mobile app.

It has two programs, called Energise and Revitalise, and uses blue, red and near-infrared light. Unusually, you can choose which kind of light you want to use in four areas of your face: forehead, eyes, nose, cheeks and chin. In my tests, I liked being able to treat spots on my chin with blue light while using red light on the rest of my face.

It didn’t make the final cut because … it’s not very comfortable. Since the battery is on the mask itself, it’s a little top heavy, and the eye protectors don’t do a great job of shielding your eyes. I also hate having lots of apps on my phone – it’s up to you whether the wireless freedom is worth the app installation.

N umber of LEDs: 80; n umber of settings: two presets, with in-app personalisation options across five facial zones; treatment time: 10mins; light frequencies: red light (630nm), near-infrared light (830nm), blue light (415nm); timer countdown: yes

Lustre

ClearSkin Renew Pro Facewear

from £224.99

What we love
App control for personalised treatments

What we don’t love
Less comfortable to wear


Silk’n LumiLips LED lip mask

Silk’n

LumiLips LED lip mask

from £79

What we love
Deep near-infrared light and concentrated treatment

What we don’t love
Less comfortable to wear than a mask

Silk n Lumilips LED mask which is white and oversized lip shaped. It glows red underneath on to the table.
Photograph: Sarah Matthews/The Guardian
£79 at Lookfantastic
£80 at Boots

Best for: targeted lip treatments

If your main area of concern is the lip area, you might not need to buy a full mask. The Silk’n LumiLips has 30 LEDs concentrated in the lip area, covering smile lines and the chin. It has five light frequencies – amber, red, dark red, near-infrared and deep near-infrared. The only other mask on this roundup offering deep near-infrared light is the CurrentBody 2 mask, which gives you a good idea of how much value it offers.

The mask has two modes, both of which use dark red, near-infrared and deep near-infrared light. The red-light mode claims to promote lip volume and firmness , while the second mode adds in amber light to reduce pigmentation and redness. I love that the mask requires only a five-minute daily treatment, making its less-than-comfortable mouthpiece slightly more bearable.

It didn’t make the final cut because … it’s built like an adult pacifier and feels like one too. You have to bite down on the mouthpiece to keep it in place, which is far less comfortable than just wearing a mask with a strap around your head.

N umber of LEDs: 30; number of settings: two; treatment time: 5mins; light frequencies: amber (605nm), red (633nm), dark red (660nm), near-infrared (830nm), deep near-infrared (1,072nm); timer countdown: no

Silk’n

LumiLips LED lip mask

from £79

What we love
Deep near-infrared light and concentrated treatment

What we don’t love
Less comfortable to wear than a mask


Peep Club heated eye wand LED+

Peep Club

Heated eye wand LED+

from £85

What we love
Dedicated, soothing treatment for eye area

What we don’t love
Small LED light coverage

Best light therapy mask-Peep club heated eye wand LED-3.JPG
Photograph: Sarah Matthews/The Guardian
£85 at Peep Club
£85 at Victoria Health

Best for: reviving and soothing the undereyes

LED face masks need eye guards to protect your eyes from the light, which means they neglect to treat the delicate skin underneath – an area particularly prone to fine lines, wrinkles and discoloration.

The Peep Club heated eye wand is a nifty little gadget that was designed in collaboration with optometrists, primarily as a hot compress to help with dry, tired eyes. The LED+ model includes a small LED light, which glows red to reduce fine lines and amber to decrease the visible blood vessels that cause dark circles. There’s also green light for soothing inflammation, although the evidence around green light is shaky.

During testing, I found it soothed my irritated eyes after long days staring at a screen. The amber light setting seemed to reduce my dark circles, too, after a few weeks of consistent use. As recommended, I used it with the Peep Club coconut eye balm to give the wand a bit of slip, which avoided irritating the delicate skin under my eyes.

It didn’t make the final cut because … it’s not as convenient to use as a dedicated mask, since you have to glide it over the skin. Its LED light is small, so you need to dedicate a lot of time to treatment to get the best results. While I love using the coconut eye balm and a 40ml tub lasts a long time, it leaves an oily slip on the skin after treatment, and the need for this extra running cost may be off-putting.

Number of LEDs: not listed; number of settings: five, three with LED; treatment time: 5mins; light frequencies : amber (605nm), red (633nm), green (525nm); timer countdown: yes

Peep Club

Heated eye wand LED+

from £85

What we love
Dedicated, soothing treatment for eye area

What we don’t love
Small LED light coverage


What you need to know

The reverse of the Filkeze mask with LED bulbs showing.
Several LED colours are available, with each wavelength claiming to target a different skin concern. Photograph: Sarah Matthews/The Guardian

What is LED therapy, and how does it work?

“LED (light-emitting diode) therapy is a non-invasive treatment that uses specific wavelengths of light to stimulate various cellular processes in the skin,” says aesthetic medicine expert Kubicka. “Depending on the colour or wavelength, LED light can target inflammation, promote collagen production, accelerate healing and even kill bacteria.”

Light therapy is a great addition to your skincare routine – for me, it’s helped reduce breakouts, improve healing and reduce the appearance of my acne scars. LED face masks are quick, gentle and non-invasive, and suitable for most skin types (although as mentioned above, blue light can worsen hyperpigmentation on darker skin tones, according to the experts I spoke with). The masks are effective and foolproof to use, and the daily treatments also force you to take a little time for yourself – perfect for a morning pick-me-up or an evening wind-down.

Does red light help with anti-ageing?

“Red-light therapy can reduce the appearance of fine lines and wrinkles through a process called photobiomodulation,” says consultant dermatologist Phillips. “It energises mitochondria, which are the batteries of the cells, powering the production of collagen and elastin by fibroblasts, the factories of the skin.”

Elastin and collagen are “the building blocks of firm, youthful skin”, says Kubicka. Stimulating the production of these molecules can “improve skin density, elasticity and overall smoothness” as long as you complete treatments regularly.

I have yet to develop fine lines or wrinkles, but I’m keen to avoid them by using red-light therapy for “preventive ageing”. However, “most of the clinical evidence focuses on treating visible signs of ageing or repairing damaged skin, rather than long-term prevention in younger skin,” as aesthetic doctor Verma explains.

Still, Verma reassured me my efforts wouldn’t be in vain. “Using LED light consistently and appropriately may help support overall skin health […] especially when combined with sun protection and a good skincare routine.”

What different colours of light therapy are available?

Several colours are available, with each wavelength claiming to target a different skin concern. These colours correlate to the visible light spectrum, and each can have a different effect on the skin.

Red light has a wavelength of between 630 and 700nm and is the most widely known form of light therapy, loved for its non-invasive potential anti-ageing benefits. Near-infrared light above 700nm “penetrates the skin more deeply to support tissue repair and reduce inflammation”, according to Kubicka. Blue light therapy (415nm), on the other hand, has been proven to target acne-causing bacteria, leading to a reduction in breakouts over time. Kubicka also says blue light can help regulate oil production – another common problem for those with acne.

The effect of some types of light on the skin are better researched than others. Near-infrared , red light and blue light are backed by scientific studies that identify the biological processes that each type of light triggers in the body.

Meanwhile, research into green and yellow light is more limited. One study questions the efficacy of yellow light therapy and claims that a previous study may have been influenced by the placebo effect. Similarly, a study on green light therapy suggests that more research is needed to provide a solid recommendation for use as an anti-ageing treatment.

How and when would you recommend using light therapy?

The “how” is simple: always use light therapy masks on freshly washed, dry skin, before applying serums and creams. This will give the light the most direct access to the skin.

Despite what some instruction manuals advise, don’t jump into daily treatments straight away – you may end up with slightly irritated skin. Start by introducing treatments two to three times a week, and monitoring the impact on your skin. If you don’t notice any sensitivity, you can incorporate more treatments, if permitted by the manufacturer’s guidelines.

Once your skin is used to the treatment, “home devices should be used three to five times a week, for 10-20 minutes a session,” says Phillips. Don’t expect instant results, though. If you’re hoping to treat breakouts, you should “see a reduction in redness and the frequency of acne breakouts within two to four weeks”. Those using red light for anti-ageing benefits will need to wait a little longer: “It typically takes six to eight weeks to see visible changes.”

Is light therapy safe for all skin tones?

“LED light therapy is generally very safe when used correctly,” says Verma. This is because, unlike laser hair removal, it only uses low-level, non-thermal light. “The most common side effects are mild and temporary, such as slight redness, dryness or irritation.”

“People with known photosensitive disorders or taking medications that make them more sensitive to light (eg certain antibiotics) should consult their doctor,” says Phillips. He also warns that those with darker skin tones should exercise caution when using blue light, since “some blue wavelengths have been associated with hyperpigmentation”. The Lustre ClearSkin Solo patches recommended above offer exclusively blue light, but the other masks on this roundup have blue-light-free settings if you do find that it causes sensitivity.

How much should I spend on an LED therapy mask?

There are hundreds of light therapy masks available at different prices, but the quality varies wildly. You may see results from a budget-friendly mask, such as the £100 Silk’n mask , but spending more will generally get you a larger quantity of bulbs that offer a greater range of wavelengths. You’re also more likely to get a mask with a better fit and coverage.

The best mask for you will depend on your skin concerns and budget. Those hoping to invest in a mask with anti-acne properties will be able to spend less, since blue light is more widely available, but if you’re looking for the best anti-ageing deep near-infrared light therapy, you will need to part with more cash.

High-end red light therapy masks can cost up to £500; if you spend that much, just make sure you use it regularly, or you won’t see results.


Sarah Matthews is a consumer journalist who specialises in health and beauty reviews. In her four years of product testing, she’s worked her way through countless hair styling tools, hair removal, light therapy and skincare innovations. She’s seen beauty trends come and go, and can sniff out a fad from a game changer (that doesn’t mean she’s disciplined enough to always follow her own advice, though)

Inside Fallout, gaming’s most surprising TV hit

Guardian
www.theguardian.com
2025-12-17 15:00:09
With ​a blend of retro-futurism, moral ambiguity and monster-filled wastelands, Fallout season 2 became an unlikely prestige television favourite. Now there is something a bigger, stranger and funnier journey ahead • Don’t get Pushing Buttons delivered to your inbox? Sign up here The Fallout TV seri...
Original Article

T he Fallout TV series returns to Prime Video today, and it’s fair to say that everyone was pleasantly surprised by how good the first season was. By portraying Fallout’s retro-futuristic, post-apocalyptic US through three different characters, it managed to capture different aspects of the game player’s experience, too. There was vault-dweller Lucy, trying to do the right thing and finding that the wasteland made that very difficult; Max, the Brotherhood of Steel rookie, who starts to question his cult’s authority and causes a lot of havoc in robotic power armour; and the Ghoul, Walton Goggins’s breakout character, who has long since lost any sense of morality out in the irradiated wilderness.

The show’s first season ended with a revelation about who helped cause the nuclear war that trapped a group of people in underground vaults for a couple of centuries. It also left plenty of questions open for the second season – and, this time, expectations are higher. Even being “not terrible” was a win for a video game adaptation until quite recently. How are the Fallout TV show’s creators feeling now that the first season has been a success?

“We’ll take ‘not terrible’ – let’s get that on a poster,” says Jonah Nolan, the director who co-created the series with Geneva Robertson-Dworet. I’m speaking to them alongside Bethesda’s Todd Howard, director of the most recent Fallout video games. I last met with Nolan and Howard in 2024, before the first season premiered. Howard had been holding out a long time to make a Fallout adaptation, waiting for someone who seemed to really understand the series. Nolan, a lifelong player, was that person. Howard was poised with a red pen when he received the first script, but was relieved to find it was “fabulous”.

“Going into the first season everyone’s like, ‘Just get it right’,” says Howard. “We’re over the moon with the reception to the show, so this time people are coming in with more excitement and different expectations.”

Fallout: New Vegas
A criminal paradise … Fallout: New Vegas. Photograph: Bethesda

The second season is set in New Vegas, the site of 2010’s Fallout: New Vegas, which had the best writing and characters of any game in the series, even if it was a bit broken. The post-nuclear Strip was a kind of decaying criminal paradise full of warring factions and down-and-out inhabitants having as good a time as they can, given the bleak circumstances. It was shot in the real-world Nevada desert, and all over California. “It’s more of a desert vibe, a Mohave vibe, that’s so essential to that game,” says Nolan. “That dusty, blasted-out Route 66 vibe of the game is so much fun to bring into the show.”

In the show, a long time has passed since the events of the New Vegas game by the time Lucy and the Ghoul arrive in the city, but Howard says that it does reference the player’s journey. “When you’re doing a location that gamers know so well … honouring everyone’s journey through that game was a trick,” he says. “Time has moved on. What is New Vegas like now?… if you’re a fan of that game there’s so much to love in season two, visually and also with the factions and what’s going on with them.”

The Fallout TV series has a tactile feel – its creators ensured real props and sets were built, echoing the cobbled-together nature of the settlements in the games, where everyone is building stuff out of trash and every town is shoved together from whatever anyone can find. “As a sci-fi fan, so many shows I watch, I’m aware that they’re all standing in front of a blue screen,” says Robertson-Dworet. “The whole point of an adaptation, especially of a video game, is to feel like it’s real … of course, we still augment with VFX but, wherever possible, actors are actually standing in front of locations I loved seeing in the game.”

In fact, pretty much everything you see on-screen is real, even the infamously terrifying irradiated monsters, the Deathclaws. They were scary even as blobs of pixels in the original 90s Fallout games. In the show, they’re puppets, and apparently pretty frightening up close. “It was the closest look I’d ever gotten at a Deathclaw. In Fallout 4, whenever I saw one, it would instantly kill me,” laughs Nolan. “It was quite peculiar being able to stand there and stare at it.”

“Even the radscorpion puppet was amazingly scary,” adds Robertson-Dworet. “It was so big – the mama scorp, that is. The little ones were fine, they were like overgrown lobsters, but it was genuinely very scary when the puppeteer was charging the big one at me.”

The Fallout series works because it’s made by talented film-makers who are also players and with the help of the people who created the actual games. Howard is replaying Red Dead Redemption 2 at the moment and resuming a long-dormant obsession with EA’s college (American) football games; Nolan has spent the summer playing Zelda: Tears of the Kingdom with his entire family; Robertson-Dworet is still working on scripts for the show, so she’s playing a lot of New Vegas (as is her husband).

(Not everyone involved with the show is a gamer, though. In an interview with PC Gamer , Goggins the Ghoul said he had never played a Fallout game and had no intention of doing so. “No, I haven’t sat down to play the games. And I won’t. I won’t,” he said. “I won’t play the games. I’m not interested.” It’s OK, Walton, nobody is judging your gamer cred.)

The second season is coming out weekly rather than in one binge-able batch of episodes, so we will all be experiencing it differently from last season – including Howard, Nolan and Robertson-Dworet, who will now be looking out for people’s reactions every week.

“It has more depth, it’s bigger, it’s funnier, it has a lot of surprises,” says Howard. “I’m looking forward to seeing what people think.”

What to play

Year Walk, a folklore mystery.
A folklore mystery … Year Walk. Illustration: Simogo

Swedish developer Simogo made some of the most interesting iPhone and iPad games of the 2010s, from the unforgettable puzzle game Device 6 to the eerie Year Walk . It recently released a compilation of these games, an attempt to preserve them before they are either removed from mobile storefronts or become unplayable thanks to iOS updates.

Available on: Nintendo Switch/Switch 2, PC
Estimated playtime:
5-plus hours

What to read

Members of the “Clair Obscur: Expedition 33” team, a role-playing video game developed by French studio Sandfall Interactive, pose as they arrive to attend The Game Awards at the Peacock Theater in Los Angeles, California, on December 11, 2025.
Members of the multi-award winning Clair Obscur: Expedition 33 team. Photograph: Michael Tran/AFP/Getty Images
  • The Game awards took place last week, a typically brisk affair at just under four hours. Clair Obscur: Expedition 33 won nine awards, including Game of the Year, kicking off a predictable online discussion about whether it is even that good. See the full list of winners here , a rundown of the most notable trailers and announcements here , and look out for the Guardian’s games of the year list on Friday.

  • Lara Croft is back for two new Tomb Raider games, starring the self-assured version of the tank-topped action heroine from the 1990s. The first game, Catalyst, is a new adventure set in northern India, out 2027; next year we’ll see Legacy of Atlantis, a ground-up remake of the very first Tomb Raider game.

  • Good news for our young and sprightly readers: the Quickshot II , the legendary joystick beloved of many Amiga and C64 players, is making a comeback in January. It will work with anything with a USB slot, including all the recent modern reissues of Amiga, Commodore and Spectrum home computers.

What to click

Question Block

ball x pit
More fun for two … Ball x Pit Photograph: Kenny Sun/Devolver Digital

Reader Laura asks:

“We love games we can play as a pair, whether they are designed as single-player (e g Blue Prince) or multiplayer (e g For the King, Gloomhaven, Sunderfolk). Puzzle games and turn-based games seem to work particularly well. Do you have any suggestions for something to try next?”

We’ve answered a few variations of this question before, but as it’s Christmas, I suspect that plenty of people will be looking for something to play while cosied up on the sofa – so here are some fresh recommendations for local multiplayer and pad-passing games. If you like a challenge, Absolum is a punishing but stylish fusion of beat-em-up and adventure game. Powerwash Simulator 2 lets you soothingly scrub down filthy objects together. For nominally single-player games, narrative games often make good pad-passers; Lost Records: Bloom and Rage and Dispatch are two of the year’s best. You might want to try trading attempts at Baby Steps , the year’s most infuriating game. And my partner enjoyed taking turns at Ball x Pit , the fiendishly compelling game where you defeat demonic hordes with magic ping-pong balls.

If you’ve got a question for Question Block – or anything else to say about the newsletter – hit reply or email us on pushingbuttons@theguardian.com .

[$] The Civil Infrastructure Platform after (nearly) ten years

Linux Weekly News
lwn.net
2025-12-17 14:53:26
The Civil Infrastructure Platform (CIP) first launched in that form in April 2016, so it has a tenth-anniversary celebration in its near future. At the 2025 Open Source Summit Japan, Yoshitake Kobayashi talked about the goals of this project and where it is headed in the future. Supporting a Linux...
Original Article

The page you have tried to view ( The Civil Infrastructure Platform after (nearly) ten years ) is currently available to LWN subscribers only.

Reader subscriptions are a necessary way to fund the continued existence of LWN and the quality of its content.

If you are already an LWN.net subscriber, please log in with the form below to read this content.

Please consider subscribing to LWN . An LWN subscription provides numerous benefits, including access to restricted content and the warm feeling of knowing that you are helping to keep LWN alive.

(Alternatively, this item will become freely available on December 25, 2025)

Hochul's Powerful Pen

hellgate
hellgatenyc.com
2025-12-17 14:45:39
Hundreds of bills await their fate—and more news for your Wednesday....
Original Article

It's Wednesday, you deserve a treat, like an episode of the Hell Gate Podcast! Listen here , or wherever you get your podcasts.

Governor Kathy Hochul has a pile of homework (legislation) to get through that will affect everything from whether New Yorkers can die by medically-assisted suicide, to imposing regulations on artificial intelligence companies to prevent them from creating weapons.

Right now, the governor has 124 bills on her desk, her office told us this morning, meaning she has 10 days to sign them, veto them, or do nothing, and they become law. (Bills that aren't sent to the governor's desk by the end of the year that were passed by the legislature get one extra month of the new year before they expire.) It's a frantic time for lawmakers whose bills have already passed both the New York State Senate and Assembly, but whose legislative dreams still hang in the balance: Will they be blessed this week with the governor's penstroke, or will they die under her veto?

Give us your email to read the full story

Sign up now for our free newsletters.

Sign up

Sven Hoexter: exfatprogs: Do not try defrag.exfat / mkfs.exfat Windows compatibility in Trixie

PlanetDebian
sven.stormbind.net
2025-12-17 14:38:52
exfatprogs 1.3.0 added a new defrag.exfat utility which turned out to be not reliable and cause data loss. exfatprogs 1.3.1 disabled the utility, and I followed that decision with the upload to Debian/unstable yesterday. But as usual it will take some time until it's migrating to testing. Thus if yo...
Original Article

exfatprogs 1.3.0 added a new defrag.exfat utility which turned out to be not reliable and cause data loss. exfatprogs 1.3.1 disabled the utility , and I followed that decision with the upload to Debian/unstable yesterday. But as usual it will take some time until it's migrating to testing. Thus if you use testing do not try defag.exfat ! At least not without a vetted and current backup.

Beside of that there is a compatibility issue with the way mkfs.exfat , as shipped in trixie (exfatprogs 1.2.9), handles drives which have a physical sector size of 4096 bytes but emulate a logical size of 512 bytes. With exfatprogs 1.2.6 a change was implemented to prefer the physical sector size on those devices. That turned out to be not compatible with Windows, and was reverted in exfatprogs 1.3.0. Sadly John Ogness ran into the issue and spent some time to debug it. I've to admit that I missed the relevance of that change. Huge kudos to John for the bug report. Based on that I prepared an update for the next trixie point release .

If you hit that issue on trixie with exfatprogs 1.2.9-1 you can work around it by formating with mkfs.exfat -s 512 /dev/sdX to get Windows compatibility. If you use exfatprogs 1.2.9-1+deb13u1 or later, and want the performance gain back, and do not need Windows compatibility, you can format with mkfs.exfat -s 4096 /dev/sdX .

A Safer Container Ecosystem with Docker: Free Docker Hardened Images

Lobsters
www.docker.com
2025-12-17 14:38:02
Comments...
Original Article

Containers are the universal path to production for most developers, and Docker has always been the steward of the ecosystem. Docker Hub has over 20 billion monthly pulls, with nearly 90% of organizations now relying on containers in their software delivery workflows. That gives us a responsibility: to help secure the software supply chain for the world.

Why? Supply-chain attacks are exploding. In 2025, they caused more than $60 billion in damage, tripling from 2021. No one is safe. Every language, every ecosystem, every build and distribution step is a target.

For this reason, we launched Docker Hardened Images (DHI), a secure, minimal, production-ready set of images, in May 2025, and since then have hardened over 1,000 images and helm charts in our catalog. Today, we are establishing a new industry standard by making DHI freely available and open source to everyone who builds software. All 26 Million+ developers in the container ecosystem. DHI is fully open and free to use, share, and build on with no licensing surprises, backed by an Apache 2.0 license. DHI now gives the world a secure, minimal, production-ready foundation from the very first pull.

If it sounds too good to be true, here’s the bottom line up front: every developer and every application can (and should!) use DHI without restrictions. When you need continuous security patching, applied in under 7 days, images for regulated industries (e.g., FIPS, FedRAMP), you want to build customized images on our secure build infrastructure, or you need security patches beyond end-of-life, DHI has commercial offerings. Simple.

Since the introduction of DHI, enterprises like Adobe and Qualcomm have bet on Docker for securing their entire enterprise to achieve the most stringent levels of compliance, while startups like Attentive and Octopus Deploy have accelerated their ability to get compliance and sell to larger businesses.

Now everyone and every application can build securely from the first docker build . Unlike other opaque or proprietary hardened images, DHI is compatible with Alpine and Debian, trusted and familiar open source foundations teams already know and can adopt with minimal change. And while some vendors suppress CVEs in their feed to maintain a green scanner, Docker is always transparent, even when we’re still working on patches, because we fundamentally believe you should always know what your security posture is. The result: dramatically reduced CVEs (guaranteed near zero in DHI Enterprise), images up to 95 percent smaller, and secure defaults without ever compromising transparency or trust.

There’s more. We’ve already built Hardened Helm Charts to leverage DHI images in Kubernetes environments; those are open source too. And today, we’re expanding that foundation with Hardened MCP Servers. We’re bringing DHI’s security principles to the MCP interface layer, the backbone of every agentic app. And starting now, you can run hardened versions of the MCP servers developers rely on most: Mongo, Grafana, GitHub, and more. And this is just the beginning. In the coming months, we will extend this hardened foundation across the entire software stack with hardened libraries, hardened system packages, and other secure components everyone depends on. The goal is simple: be able to secure your application from main() down.


The philosophy of Docker Hardened Images

Base images define your application’s security from the very first layer, so it’s critical to know exactly what goes into them. Here’s how we approach it.

First: total transparency in every part of our minimal, opinionated, secure images.

DHI uses a distroless runtime to shrink the attack surface while keeping the tools developers rely on. But security is more than minimalism; it requires full transparency. Too many vendors blur the truth with proprietary CVE scoring, downgraded vulnerabilities, or vague promises about reaching SLSA Build Level 3.

DHI takes a different path. Every image includes a complete and verifiable SBOM. Every build provides SLSA Build Level 3 provenance. Every vulnerability is assessed using transparent public CVE data; we won’t hide vulnerabilities when we haven’t fixed them. Every image comes with proof of authenticity. The result: a secure foundation you can trust, built with clarity, verified with evidence, and delivered without compromise.

Second: Migrating to secure images takes real work, and no one should pretend otherwise. But as you’d expect from Docker, we’ve focused on making the DX incredibly easy to use. As we mentioned before, DHI is built on the open source foundations the world already trusts, Debian and Alpine, so teams can adopt it with minimal friction.  We’re reducing that friction even more: Docker’s AI assistant can scan your existing containers and recommend or even apply equivalent hardened images; the feature is experimental as this is day one, but we’ll quickly GA it as we learn from real world migrations.

Lastly: we think about the most aggressive SLAs and longest support times and make certain that every piece of DHI can support that when you need it.

DHI Enterprise, the commercial offering of DHI, includes a 7-day commitment for critical CVE remediation, with a roadmap toward one day or less. For regulated industries and mission-critical systems, this level of trust is mandatory. Achieving it is hard. It demands deep test automation and the ability to maintain patches that diverge from upstream until they are accepted. That is why most organizations cannot do this on their own. In addition, DHI Enterprise allows organizations to easily customize DHI images, leveraging Docker’s build infrastructure which takes care of the full image lifecycle management for you, ensuring that build provenance and compliance is maintained. For example, typically organizations need to add certificates and keys, system packages, scripts, and so on. DHI’s build service makes this trivial.

Because our patching SLAs and our build service carry real operational cost, DHI has historically been one commercial offering. But our vision has always been broader. This level of security should be available to everyone, and the timing matters. Now that the evidence, infrastructure, and industry partnerships are in place, we are delivering on that vision. That is why today we are making Docker Hardened Images free and open source.

This move carries the same spirit that defined Docker Official Images over a decade ago. We made them free, kept them free, and backed them with clear docs, best practices, and consistent maintenance. That foundation became the starting point for millions of developers and partners.

Now we’re doing it again. DHI being free is powered by a rapidly growing ecosystem of partners, from Google, MongoDB, and the CNCF delivering hardened images to security platforms like Snyk and JFrog Xray integrating DHI directly into their scanners. Together, we are building a unified, end-to-end supply chain that raises the security bar for the entire industry.

“Docker’s move to make its hardened images freely available under Apache 2.0 underscores its strong commitment to the open source ecosystem. Many CNCF projects can already be found in the DHI catalog, and giving the broader community access to secure, well-maintained building blocks helps us strengthen the software supply chain together. It’s exciting to see Docker continue to invest in open collaboration and secure container infrastructure.”

Jonathan Bryce

Executive Director at the Cloud Native Computing Foundation

“Software supply chain attacks are a severe industry problem. Making Docker Hardened Images free and pervasive should underpin faster, more secure software delivery across the industry by making the right thing the easy thing for developers.”

James Governor

Analyst and Co-founder, RedMonk

“Security shouldn’t be a premium feature. By making hardened images free, Docker is letting every developer, not just big enterprises, start with a safer foundation. We love seeing tools that reduce noise and toil, and we’re ready to run these secure workloads on Google Cloud from day one”

Ryan J. Salva

Senior Director of Product at Google, Developer Experiences

“At MongoDB, we believe open source plays a central role in how modern software is built, enabling flexibility, choice, and developer productivity. That’s why we’re excited about free Docker Hardened Images for MongoDB. These images provide trusted, ready-to-deploy building blocks on proven Linux foundations such as Alpine and Debian, and with an Apache 2.0 license, they remain fully open source and free for anyone to use. With Docker Hub’s global reach and MongoDB’s commitment to reliability and safety, we are making it easier to build with confidence on a secure and open foundation for the future”

Jim Scharf

Chief Technology Officer, MongoDB

“We’re excited to partner with Docker to deliver secure, enterprise-grade AI workloads from development to production. With over 50 million users and the majority of Fortune 500 trusting Anaconda to help them operate at enterprise scale securely, this partnership with Docker brings that same foundation to Docker Hardened Images. This enables teams to spend less time managing risk and more time innovating, while reducing the time from idea to production.”

David DeSanto

Chief Executive Officer, Anaconda

“Socket stops malicious packages at install time, and Docker Hardened Images (DHI) give those packages a trustworthy place to run. With free DHI, teams get both layers of protection without lifting a finger. Pull a hardened image, run npm install, and the Socket firewall embedded in the DHI is already working for you. That is what true secure-by-default should look like, and we’re excited to partner with Docker and make it happen at their scale.”

Feross Aboukhadijeh

Founder and CEO, Socket

“Teams building with Temporal orchestrate mission-critical workflows, and Docker is how they deploy those services in production. Making Docker Hardened Images freely available gives our users a very strong foundation for those workflows from day one, and Extended Lifecycle Support helps them keep long running systems secure without constant replatforming.”

Maxim Fateev

Chief Technology Officer, Temporal

“At CircleCI, we know teams need to validate code as fast as they can generate it—and that starts with a trusted foundation. Docker Hardened Images eliminate a critical validation bottleneck by providing pre-secured, continuously verified components right from the start, helping teams ship fast, with confidence.”

Rob Zuber

Chief Technology Officer, CircleCI

“We evaluated multiple options for hardened base images and chose Docker Hardened Images (DHI) for its alignment with our supply chain security posture, developer tooling compatibility, Docker’s maturity in this space, and integration with our existing infrastructure. Our focus was on balancing trust, maintainability, and ecosystem compatibility.”

Vikram Sethi

Principal Scientist, Adobe

A Secure Path for Every Team and Business

Everyone now has a secure foundation to start from with DHI. But businesses of all shapes and sizes often need more. Compliance requirements and risk tolerance may demand CVE patches ahead of upstream the moment the source becomes available. Companies operating in enterprise or government sectors must meet strict standards such as FIPS or STIG. And because production can never stop, many organizations need security patching to continue even after upstream support ends.

That is why we now offer three DHI options, each built for a different security reality.

Docker Hardened Images: Free for Everyone. DHI is the foundation modern software deserves: minimal hardened images, easy migration, full transparency, and an open ecosystem built on Alpine and Debian.

Docker Hardened Images (DHI) Enterprise: DHI Enterprise delivers the guarantees that organizations, governments, and institutions with strict security or regulatory demands rely on. FIPS-enabled and STIG-ready images. Compliance with CIS benchmarks. SLA-backed remediations they can trust for critical CVEs in under 7 days. And those SLAs keep getting shorter as we push toward one-day (or less) critical fixes.

For teams that need more control, DHI Enterprise delivers. Change your images. Configure runtimes. Install tools like curl. Add certificates. DHI Enterprise gives you unlimited customization, full catalog access, and the ability to shape your images on your terms while staying secure.

DHI Extended Lifecycle Support (ELS): ELS is a paid add-on to DHI Enterprise, built to solve one of software’s hardest problems. When upstream support ends, patches stop but vulnerabilities don’t. Scanners light up, auditors demand answers, and compliance frameworks expect verified fixes. ELS ends that cycle with up to five additional years of security coverage, continuous CVE patches, updated SBOMs and provenance, and ongoing signing and auditability for compliance.

You can learn more about these options here .

Here’s how to get started

Securing the container ecosystem is something we do together. Today, we’re giving the world a stronger foundation to build on. Now we want every developer, every open source project, every software vendor, and every platform to make Docker Hardened Images the default.

Lastly, we are just getting started, and if you’re reading this and want to help build the future of container security, we’d love to meet you. Join us.

Authors’ Notes

Christian Dupuis

Today’s announcement marks a watershed moment for our industry. Docker is fundamentally changing how applications are built-secure by default for every developer, every organization, and every open-source project.

This moment fills me with pride as it represents the culmination of years of work: from the early days at Atomist building an event-driven SBOM and vulnerability management system, the foundation that still underpins Docker Scout today, to unveiling DHI earlier this year, and now making it freely available to all. I am deeply grateful to my incredible colleagues and friends at Docker who made this vision a reality, and to our partners and customers who believed in us from day one and shaped this journey with their guidance and feedback.

Yet while this is an important milestone, it remains just that, a milestone. We are far from done, with many more innovations on the horizon. In fact, we are already working on what comes next.

Security is a team sport, and today Docker opened the field to everyone. Let’s play.

Michael Donovan

I joined Docker to positively impact as many developers as possible. This launch gives every developer the right to secure their applications without adding toil to their workload. It represents a monumental shift in the container ecosystem and the digital experiences we use every day.

I’m extremely proud of the product we’ve built and the customers we serve every day. I’ve had the time of my life building this with our stellar team and I’m more excited than ever for what’s to come next.

Security updates for Wednesday

Linux Weekly News
lwn.net
2025-12-17 14:19:48
Security updates have been issued by Debian (node-url-parse), Fedora (assimp, conda-build, mod_md, util-linux, and webkitgtk), Oracle (firefox), SUSE (chromium, librsvg, poppler, python311, qemu, strongswan, webkit2gtk3, wireshark, and xen), and Ubuntu (linux-azure, linux-azure-5.4, linux-azure-5.15...
Original Article
Dist. ID Release Package Date
Debian DLA-4413-1 LTS node-url-parse 2025-12-16
Fedora FEDORA-2025-0f4b31c58e F43 assimp 2025-12-17
Fedora FEDORA-2025-eb0eab6793 F42 conda-build 2025-12-17
Fedora FEDORA-2025-7b0d558ac5 F42 mod_md 2025-12-17
Fedora FEDORA-2025-24282560e4 F43 mod_md 2025-12-17
Fedora FEDORA-2025-40fe2fec53 F43 util-linux 2025-12-17
Fedora FEDORA-2025-7536d2d941 F42 webkitgtk 2025-12-17
Oracle ELSA-2025-17453 OL7 firefox 2025-12-16
Oracle ELSA-2025-19278 OL7 firefox 2025-12-16
Oracle ELSA-2025-22371 OL7 firefox 2025-12-16
SUSE openSUSE-SU-2025:0470-1 osB15 chromium 2025-12-16
SUSE openSUSE-SU-2025:0471-1 osB15 chromium 2025-12-16
SUSE SUSE-SU-2025:4411-1 SLE-m5.3 SLE-m5.4 SLE-m5.5 oS15.4 librsvg 2025-12-16
SUSE SUSE-SU-2025:4412-1 oS15.5 poppler 2025-12-16
SUSE SUSE-SU-2025:21207-1 SLE-m6.1 python311 2025-12-16
SUSE openSUSE-SU-2025:15821-1 TW qemu 2025-12-16
SUSE openSUSE-SU-2025:15822-1 TW strongswan 2025-12-16
SUSE SUSE-SU-2025:4416-1 MP4.3 SLE15 webkit2gtk3 2025-12-16
SUSE SUSE-SU-2025:4413-1 SLE15 wireshark 2025-12-16
SUSE SUSE-SU-2025:4419-1 SLE15 xen 2025-12-17
Ubuntu USN-7939-1 18.04 20.04 linux-azure, linux-azure-5.4 2025-12-16
Ubuntu USN-7939-1 18.04 20.04 linux-azure, linux-azure-5.4 2025-12-16
Ubuntu USN-7938-1 20.04 linux-azure-5.15 2025-12-16
Ubuntu USN-7939-2 20.04 linux-azure-fips 2025-12-16
Ubuntu USN-7889-7 24.04 linux-raspi, linux-raspi-realtime, linux-xilinx 2025-12-16

Hack Reveals the a16z-Backed Phone Farm Flooding TikTok With AI Influencers

403 Media
www.404media.co
2025-12-17 14:13:00
A hacker gained control of a 1,100 mobile phone farm powering covert, AI-generated ads on TikTok....
Original Article

Doublespeed, a startup backed by Andreessen Horowitz (a16z) that uses a phone farm to manage at least hundreds of AI-generated social media accounts and promote products has been hacked. The hack reveals what products the AI-generated accounts are promoting, often without the required disclosure that these are advertisements, and allowed the hacker to take control of  more than 1,000 smartphones that power the company.

The hacker, who asked for anonymity because he feared retaliation from the company, said he reported the vulnerability to Doublespeed on October 31. At the time of writing, the hacker said he still has access to the company’s backend, including the phone farm itself. Doublespeed did not respond to a request for comment.

“I could see the phones in use, which manager (the PCs controlling the phones) they had, which TikTok accounts they were assigned, proxies in use (and their passwords), and pending tasks. As well as the link to control devices for each manager,” the hacker told me. “I could have used their phones for compute resources, or maybe spam. Even if they're just phones, there are around 1100 of them, with proxy access, for free. I think I could have used the linked accounts by puppeting the phones or adding tasks, but haven't tried.”

As I reported in October, Doublespeed raised $1 million from a16z as part of its “ Speedrun ” accelerator program, “a fast‐paced, 12-week startup program that guides founders through every critical stage of their growth.” Doublespeed uses generative AI to flood social media with accounts and posts to promote certain products on behalf of its clients. Social media companies attempt to detect and remove this type of astroturfing for violating their inauthentic behavior policies, which is why Doublespeed uses a bank of phones to emulate the behavior of real users. So-called “click farms” or “phone farms” often use hundreds of mobile phones to fake online engagement of reviews for the same reason.

The hacker told me he had access to around 1,100 smartphones Doublespeed operates. One way the hacker proved he had access to devices was by taking control of one phone’s camera, which seemingly showed it in a rack with other phones.

Images the hacker captured from some of the phones in Doublespeed's phone farm.

The hacker also shared a list with me of more than 400 TikTok accounts Doublespeed operates. Around 200 of those were actively promoting products on TikTok, mostly without disclosing the posts were ads, according to 404 Media’s review of them. It’s not clear if the other 200 accounts ever promoted products or were being “warmed up,” as Doublespeed describes the process of making the accounts appear authentic before it starts promoting in order to avoid a ban.

I’ve seen TikTok accounts operated by Doublespeed promote language learning apps, dating apps, a Bible app, supplements, and a massager.

One health-themed Doublespeed Tiktok account named Chloe Davis posted almost 200 slideshows featuring a middle-aged AI-generated woman. In the posts, the woman usually discusses various physical ailments and how she deals with them. The last image in the slide always includes a picture of someone using a massage roller from a company called Vibit. Vibit did not respond to a request for comment.

A Doublespeed TikTok account promoting a Vibit massager.

Another Doublespeed-operated TikTok account named pattyluvslife posted dozens of slideshows of a young woman who, according to her bio, is a student at UCLA. All the posts from this account talk about how “big pharma” and the supplements industry is a scam. But the posts also always promoted a moringa supplement from a company called Rosabella. The AI-generated woman in these TikTok posts often holds up the bottle of supplements, but it’s obviously AI-generated as the text on the bottle is jumbled gibberish.

An AI-generated image promoting a Rosabella supplement.

Rosabella’s site also claims the product is “viral on TikTok.” Rosabella did not respond to a request for comment.

An image from Rosabella's site claiming its brand is viral on TikTok.

While most of the content I’ve seen on Doublespeed-operated TikTok accounts included AI-generated slideshows and still images, Doublespeed is also able to AI-generate videos as well. One Doublespeed-operated account posted several AI-generated videos of a young woman voguing at the camera. The account was promoting a company called Playkit, a “TikTok content agency” that pays users to promote products on behalf of its clients. Notably, this is the exact kind of business Doublespeed would in theory be able to replace with AI-generated accounts. Playkit did not respond to a request for comment.

0:00

/ 0:04

An AI-generated video promoting Playkit, a TikTok content agency.

TikTok told me that its Community Guidelines make clear that it requires creators to label AI-generated or significantly edited content that shows realistic-looking scenes or people. After I reached out for comment, TikTok added a label to the Doublespeed-operated accounts I flagged indicating they're AI-generated.

A16z did not respond to a request for comment.

Doublespeed has said it has the ability to and soon plans to launch its services on Instagram, Reddit, and X, but so far seems to only be operating on TikTok. In October , a Reddit spokesperson told me that Doublespeed’s service would violate its terms of service. Meta did not respond to a request for comment. As we noted in October, Marc Andreessen, after whom half of Andreessen Horowitz is named, sits on Meta’s board of directors. Doublespeed’s business would clearly violate Meta’s policy on “authentic identity representation.”

About the author

Emanuel Maiberg is interested in little known communities and processes that shape technology, troublemakers, and petty beefs. Email him at emanuel@404media.co

Emanuel Maiberg

Dirk Eddelbuettel: RcppArmadillo 15.2.3-1 on CRAN: Upstream Update

PlanetDebian
dirk.eddelbuettel.com
2025-12-17 14:11:00
Armadillo is a powerful and expressive C++ template library for linear algebra and scientific computing. It aims towards a good balance between speed and ease of use, has a syntax deliberately close to Matlab, and is useful for algorithm development directly in C++, or quick conversion of research ...
Original Article

RcppArmadillo 15.2.3-1 on CRAN: Upstream Update

armadillo image

Armadillo is a powerful and expressive C++ template library for linear algebra and scientific computing. It aims towards a good balance between speed and ease of use, has a syntax deliberately close to Matlab, and is useful for algorithm development directly in C++, or quick conversion of research code into production environments. RcppArmadillo integrates this library with the R environment and language–and is widely used by (currently) 1272 other packages on CRAN , downloaded 43.2 million times (per the partial logs from the cloud mirrors of CRAN), and the CSDA paper ( preprint / vignette ) by Conrad and myself has been cited 661 times according to Google Scholar.

This versions updates to the 15.2.3 upstream Armadillo release from yesterday. It brings minor changes over the RcppArmadillo 15.2.2 release made last month (and described in this post ). As noted previously, and due to both the upstream transition to C++14 coupled with the CRAN move away from C++11, the package offers a transition by allowing packages to remain with the older, pre-15.0.0 ‘legacy’ Armadillo yet offering the current version as the default. If and when CRAN will have nudged (nearly) all maintainers away from C++11 (and now also C++14 !!) we can remove the fallback. Our offer to help with the C++ modernization still stands, so please get in touch if we can be of assistance. As a reminder, the meta-issue #475 regroups all the resources for the C++11 transition.

There were no R-side changes in this release. The detailed changes since the last release follow.

Changes in RcppArmadillo version 15.2.3-1 (2025-12-16)

  • Upgraded to Armadillo release 15.2.3 (Medium Roast Deluxe)

    • Faster .resize() for vectors

    • Faster repcube()

Courtesy of my CRANberries , there is a diffstat report relative to previous release. More detailed information is on the RcppArmadillo page . Questions, comments etc should go to the rcpp-devel mailing list off the Rcpp R-Forge page.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub .

/code/rcpp | permanent link

Podcast: Is Wiping a Phone a Crime?

403 Media
www.404media.co
2025-12-17 14:00:08
A man was charged for allegedly wiping a phone before CBP could search it; an Anthropic exec forced AI onto a Discord community that didn't want it; and we talk the Disney-OpenAI deal....
Original Article

Joseph had to use a different mic this week, that will be fixed next time! We start this week talking about a very unusual case: someone is being charged for allegedly wiping a phone before CBP could search it. There are a lot of questions remaining, but a super interesting case. After the break, we talk about Matthew’s article on an Anthropic exec forcing AI onto a queer gamer Discord. In the subscribers-only section, we all chat about the Disney and OpenAI deal.

Listen to the weekly podcast on Apple Podcasts , Spotify , or YouTube . Become a paid subscriber for access to this episode's bonus content and to power our journalism. If you become a paid subscriber, check your inbox for an email from our podcast host Transistor for a link to the subscribers-only version! You can also add that subscribers feed to your podcast app of choice and never miss an episode that way. The email should also contain the subscribers-only unlisted YouTube link for the extended video version too. It will also be in the show notes in your podcast player.

Timestamps:
00:48 - Man Charged for Wiping Phone Before CBP Could Search It
17:44 - Anthropic Exec Forces AI Chatbot on Gay Discord Community, Members Flee
41:17 - Disney Invests $1 Billion in the AI Slopification of Its Brand

About the author

Joseph is an award-winning investigative journalist focused on generating impact. His work has triggered hundreds of millions of dollars worth of fines, shut down tech companies, and much more.

Joseph Cox

Tell HN: HN Was Down

Hacker News
news.ycombinator.com
2025-12-17 16:48:18
Comments...
Original Article

Is this still a valid account for HN status? It says it’s the official one, but with the changes at Twitter to no longer show chronological feeds (at least for users that aren’t logged in), it’s rather useless. The top 5 listed post (for me) are seemingly random from 2014 - 2022.

https://x.com/HNStatus

Is there a better place to check, beyond a basic down detector that may provide more insight or signal that the outage is acknowledged?


https://hn.hund.io/ Is a status page, no idea if official or not, but it didn't register here for some reason.

I didn't read the post text, it's identified there haha, my bad! I wish the text post text wasn't grey, I gloss over it too easily.


It just reinforces for me that addiction is a human problem not a problem with technology

I know dang basically works tirelessly to not change the format in order to not induce those addictive patterns

but yet here we all are


It's a website with the smartest people in the world. The level of conversations here are unrivaled in internet communities.

It's understandable to be addicted. Lol.

I visit this place multiple times a day.


It's really not 'the smartest people.' It's people interested in tech, and often in making-a-lot-of-money-in-tech. It does have a lot of people with significant industry experience, which is cool.


> It's really not 'the smartest people.'

This was especially obvious during Covid, I even stopped visiting because the comment section was so crazy.


This one is at least healthy-ish for the mind. I’d much rather hacker news than any other news. Social Media is an emotional rage-bait cesspool these days. If it’s not for Hacker News those of us who abstain from the rest would be living in the dark.


I got stuck in an infinite loop.

Try opening HN -> it's down, better check HN to see everyone talking about a major website being down -> Try opening HN -> loop


I always hated the late use-it-or-loose-it at the end of the year where you end up buying the things that were denied requests from earlier in the year. You just cost me half a year of using the damn thing.


I was able to view the site without being signed in (i.e. private window) but any browser I was logged into wouldn't load.

I'm sure it's a coincidence but it started working again shortly after emailing hn@ycombinator.com


Next time you can avoid that fate by opening HN in a private browsing (or whatever your browser calls its equivalent) window. This outage, like the vast majority of HN outages, only affected logged in requests.

I suppose you could also just clear your HN cookies in regular browsing window, but then when they fix it you'd have to log in again.


Yeah I couldn't log in for a bit this morning. It's concerning how often and how many times I tried. Glad it's resolved.


A lot of the outage indicators failed. Someone needs to create an outage indicator reliability dashboard.


A lot of them got fooled by the caching; pages for signed-out users are cached heavily and those kept returning successful responses even if the actual backend server was down.


It was the first time since I started using this website (August last year) that it was down.

I'm still impressed nonetheless.

I'd like to know what caused the outage and how it could have been prevented, for learning purposes.


> how do you keep track of his comments?

You can just look at them, turn on showdead in your profile and you'll see a bunch of flag-killed comments in this discussion by whatevermrfukz. No need for a plugin or scraper.


I got confused by the "minutes ago" thing.

Working with full dates in the HTML and doing a tiny JavaScript that calculates the "minutes ago" would actually be a neat improvement.


Just a month ago, I got downvoted to -2 for saying HN for being self-hosted hasn't shown up as more reliable than something behind Cloudflare. My point is made.

Edit: Now it happens again. Knee jerk defenses all the way down.


Unless the downtime was caused by something Cloudflare would've prevented, this downtime would've happened regardless of being behind Cloudflare. Cloudflare adds another single point of failure.


Could this be a self-inflicted bug? In that case, the broader point still stands: cloud providers can cause outages that are outside your direct realm of responsibility.


Your VPS server and your data center and the ISP your data center uses and the AS system your ISP uses all can cause outages outside your direct realm of responsibility.


It's absolutely irresistible downvoting people who preemptively complain about being downvoted like you do. It really made my day. Post another complaint so I can do it again please! It's not knee jerk when you explicitly ask for it, by leading with a complaint about downvoting, instead of just making your point and letting it fall or rise on its own merits. You're the one who put the idea of downvoting you into my head in the first place.

Ask HN: Was HN just down for anyone else?

Hacker News
news.ycombinator.com
2025-12-17 16:46:39
Comments...
Original Article

Not completely, I'm not logged in on my work laptop and it was only working some of the time (and not like some pages were cached and some weren't, I was refreshing the same page and sometimes it worked and sometimes not).


also went down if you went to login, and people's individual pages were also down. So as far as I saw the front page was up as long as you were not logged in, however I'm not sure if that wasn't just luck of the draw, I had one experience where it looked like maybe the front page was sometimes down for not logged in users as well.

on edit: ok others pointed out it was cached pages I saw. explains it.


Yes, and on one request I saw a message like "Restarting server - this won't take long", and soon after it's back up.


It was down if you tried to access it while authenticated (i.e. you have a cookie). It was loading fine for unauthenticated sessions (e.g. incognito).

Launch HN: Kenobi (YC W22) – Personalize your website for every visitor

Hacker News
news.ycombinator.com
2025-12-17 16:44:13
Comments...
Original Article

Hey HN! We’re Rory, Chris, and Felix from Kenobi ( https://kenobi.ai ). Kenobi lets you add AI-based content personalization to any website. As a site owner, you install our personalization widget with a script tag, just like you would for e.g. a chatbot integration. As a visitor, you interact with the widget (right now by providing a company name) and Kenobi changes the site content to suit you.

We’ve built a demo that anyone can try here: https://kenobi.ai/start

We believe that large parts of the web are about to go from being static to dynamic because of how adept LLMs are at transforming rendered HTML. And right now we’re focussing on B2B landing page content (as opposed to application UIs) because there is a lot of commercial opportunity for increasing top-of-funnel inbound conversions.

Our journey to Kenobi today is a long and snaking one. You may notice from the post title that we did YC’s Winter 2022 batch (I know that 4 years is practically ancient in YC-dog-years). Kenobi is a hard pivot from our original idea that we got accepted into YC with — a company called Verdn which did trackable environmental donations via an API. Since the summer, we’ve been hacking on different ideas… We started with personalized UI screenshots for outbound campaigns, but then people told us they wanted transformations to their actual site[0] — so we built an agentic workflow to research a visitor-company and “pre-render” changes to a landing site for them. Ultimately, there was too much friction in getting people to incorporate personalized URLs into their cold outbound campaigns[1]. Besides, people kept asking for us to do this for their inbound traffic, and so our current iteration was born.

Right now with Kenobi you pick a page that you’d like to make customizable, and choose [text] elements that you’d like to make dynamic. You can define custom prompting instructions for these elements, and when someone visits your page, our agentic workflow researches their company, and presents the updated content as quickly as possible, usually within a few seconds.[2] You also get a ping in Slack every time this happens so you know who is using your site.

We’ve been experimenting with features such as generating custom imagery that actually looks good and native to the page design, and pulling in company data sources so that e.g. the right case study can be presented based on a visitor’s industry and ICP profile. Our most requested feature is deanonymizing traffic so that Kenobi’s personalization can happen automatically as visitors land on your page — this is coming very soon, as right now you have to specify where you’re coming from.

It’s surprised us just how much business value we’ve gotten from knowing who (most probably) is on the page and asking for a personalized experience. We’ve seen response rates 3x of what we would normally from following people up from companies we know visited our site.

There are many players in this space already, and everyone seems to have their own angle. We are keen to hear thoughts on what people think the future of the personalized internet looks like!

Cheers from London!

P.S. - there's also a video that Chris recorded showing the end-to-end Kenobi experience right now https://www.loom.com/share/bc0a82a2f2fd40f695315bae80e8f5d8

[0] - Many of them had tried AI “microsite” generators but found the maintenance of managing a separate website(s) just for closing deals to be burdensome and inefficient.

[1] - Despite having a CSV export and Clay integration option for our pre-generated website changes, getting people to weave the URLs into their email sequences (everyone uses different tools) seemed almost insurmountable without building what would ostensibly be our own sequencing software.

[2] - We use light foundation models with grounded search for the research step, and translate these into markup changes via another light LLM pass and our own DSL which is optimized for speed.

Gemini 3 Flash: frontier intelligence built for speed

Hacker News
blog.google
2025-12-17 16:42:13
Comments...
Original Article

Gemini 3 Flash is our latest model with frontier intelligence built for speed that helps everyone learn, build, and plan anything — faster.

General summary

Google is releasing Gemini 3 Flash, a fast and cost-effective model built for speed. You can now access Gemini 3 Flash through the Gemini app and AI Mode in Search. Developers can access it via the Gemini API in Google AI Studio, Google Antigravity, Gemini CLI, Android Studio, Vertex AI and Gemini Enterprise.

Summaries were generated by Google AI. Generative AI is experimental.

Bullet points

  • "Gemini 3 Flash: frontier intelligence built for speed" introduces a fast, efficient AI model.
  • Gemini 3 Flash offers Pro-grade reasoning at Flash-level speed and a lower cost.
  • It's great for coding, complex analysis, and quick answers in interactive apps.
  • Gemini 3 Flash is now the default model in the Gemini app and AI Mode in Search.
  • Developers and everyday users can access Gemini 3 Flash via various Google platforms.

Summaries were generated by Google AI. Generative AI is experimental.

Explore other styles:

Gemini 3 Flash text

Your browser does not support the audio element.

Listen to article

This content is generated by Google AI. Generative AI is experimental

[[duration]] minutes

Today, we're expanding the Gemini 3 model family with the release of Gemini 3 Flash, which offers frontier intelligence built for speed at a fraction of the cost. With this release, we’re making Gemini 3’s next-generation intelligence accessible to everyone across Google products.

Last month, we kicked off Gemini 3 with Gemini 3 Pro and Gemini 3 Deep Think mode, and the response has been incredible. Since launch day, we have been processing over 1T tokens per day on our API. We’ve seen you use Gemini 3 to vibe code simulations to learn about complex topics, build and design interactive games and understand all types of multimodal content .

With Gemini 3, we introduced frontier performance across complex reasoning, multimodal and vision understanding and agentic and vibe coding tasks. Gemini 3 Flash retains this foundation, combining Gemini 3's Pro-grade reasoning with Flash-level latency, efficiency and cost. It not only enables everyday tasks with improved reasoning, but also is our most impressive model for agentic workflows.

Starting today, Gemini 3 Flash is rolling out to millions of people globally:

Gemini 3 Flash: frontier intelligence at scale

Gemini 3 Flash demonstrates that speed and scale don’t have to come at the cost of intelligence. It delivers frontier performance on PhD-level reasoning and knowledge benchmarks like GPQA Diamond (90.4%) and Humanity’s Last Exam (33.7% without tools), rivaling larger frontier models, and significantly outperforming even the best 2.5 model, Gemini 2.5 Pro, across a number of benchmarks. It also reaches state-of-the-art performance with an impressive score of 81.2% on MMMU Pro, comparable to Gemini 3 Pro.

A benchmark comparison table showing performance scores and prices for several language models including Gemini 3 Flash, Gemini 3 Pro Thinking, Gemini 2.5 Flash Thinking, Gemini 2.5 Pro Thinking, Claude Sonnet 4.5, GPT-5.2 Extra high, and Grok 4.1 Fast, across various tasks like academic reasoning, scientific knowledge, math, multi-modal understanding, coding, and long context performance.

In addition to its frontier-level reasoning and multimodal capabilities, Gemini 3 Flash was built to be highly efficient, pushing the Pareto frontier of quality vs. cost and speed. When processing at the highest thinking level, Gemini 3 Flash is able to modulate how much it thinks. It may think longer for more complex use cases, but it also uses 30% fewer tokens on average than 2.5 Pro, as measured on typical traffic, to accurately complete everyday tasks with higher performance.

Gemini 3 Flash pushes the Pareto frontier on performance vs. cost and speed.

A scatter plot showing LMArena Elo Score versus Price per million tokens for various language models, with a line highlighting the Pareto frontier through 'gemini-3-pro', 'gemini-3-flash', and 'gemini-3-flash-lite'.

Gemini 3 Flash’s strength lies in its raw speed, building on the Flash series that developers and consumers already love. It outperforms 2.5 Pro while being 3x faster (based on Artificial Analysis benchmarking) at a fraction of the cost. Gemini 3 Flash is priced at $0.50/1M input tokens and $3/1M output tokens (audio input remains at $1/1M input tokens).

For developers: intelligence that keeps up

Gemini 3 Flash is made for iterative development, offering Gemini 3’s Pro-grade coding performance with low latency — it’s able to reason and solve tasks quickly in high-frequency workflows. On SWE-bench Verified, a benchmark for evaluating coding agent capabilities, Gemini 3 Flash achieves a score of 78%, outperforming not only the 2.5 series, but also Gemini 3 Pro. It strikes an ideal balance for agentic coding, production-ready systems and responsive interactive applications.

Gemini 3 Flash’s strong performance in reasoning, tool use and multimodal capabilities is ideal for developers looking to do more complex video analysis, data extraction and visual Q&A, which means it can enable more intelligent applications — like in-game assistants or A/B test experiments — that demand both quick answers and deep reasoning.

We’ve received a tremendous response from companies using Gemini 3 Flash. Companies like JetBrains, Bridgewater Associates, and Figma are already using it to transform their businesses, recognizing how its inference speed, efficiency and reasoning capabilities perform on par with larger models. Gemini 3 Flash is available today to enterprises via Vertex AI and Gemini Enterprise.

For everyone: Gemini 3 Flash is rolling out globally

Gemini 3 Flash is now the default model in the Gemini app, replacing 2.5 Flash. That means all of our Gemini users globally will get access to the Gemini 3 experience at no cost, giving their everyday tasks a major upgrade.

Because of Gemini 3 Flash’s incredible multimodal reasoning capabilities, you can use it to help you see, hear and understand any type of information faster. For example, you can ask Gemini to understand your videos and images and turn that content into a helpful and actionable plan in just a few seconds.

Or you can quickly build fun, useful apps from scratch using your voice without prior coding knowledge. Just dictate to Gemini on the go, and it can transform your unstructured thoughts into a functioning app in minutes.

Gemini 3 Flash is also starting to roll out as the default model for AI Mode in Search with access to everyone around the world.

Building on the reasoning capabilities of Gemini 3 Pro, AI Mode with Gemini 3 Flash is more powerful at parsing the nuances of your question. It considers each aspect of your query to serve thoughtful, comprehensive responses that are visually digestible — pulling real-time local information and helpful links from across the web. The result effectively combines research with immediate action: you get an intelligently organized breakdown alongside specific recommendations — at the speed of Search.

This shines when tackling complex goals with multiple considerations like trying to plan a last-minute trip or learning complex educational concepts quickly.

Try Gemini 3 Flash today

Gemini 3 Flash is available now in preview via the Gemini API in Google AI Studio, Google Antigravity, Vertex AI and Gemini Enterprise . You can also access it through other developer tools like Gemini CLI and Android Studio . It’s also starting to roll out to everyone in the Gemini app and AI Mode in Search, bringing fast access to next-generation intelligence at no cost.

We’re looking forward to seeing what you bring to life with this expanded family of models: Gemini 3 Pro, Gemini 3 Deep Think and now, Gemini 3 Flash.

Hacker News down for anyone else?

Lobsters
lobste.rs
2025-12-17 14:17:24
We're having some trouble serving your request. Sorry! Tends to be a pretty reliable site, surprised to see it running into issues. Anyone else hitting the same thing?...
Original Article

We're having some trouble serving your request. Sorry!

Tends to be a pretty reliable site, surprised to see it running into issues. Anyone else hitting the same thing?

Your MFA Is Costing You Millions. It Doesn't Have To.

Bleeping Computer
www.bleepingcomputer.com
2025-12-17 14:00:00
Passwords and app-based MFA add hidden costs through lost productivity, frequent resets, and risk of phishing and social engineering attacks. Token explains how wireless biometric, passwordless authentication eliminates credential-based attacks and delivers measurable financial returns by reducing l...
Original Article

MFA Thumbprint

Token’s Wireless Biometrics Pay for Themselves Starting Day One

For nearly twenty years enterprises have been told the same thing. Authentication is a cost center. Password resets burn IT time. Authenticator apps interrupt employees. MFA deployments cost real money but still fail against common attacks. Meanwhile attackers have evolved far faster than the technologies meant to stop them. They no longer break in.

They simply log in using phishing, spoofed portals, session relays, and social engineering. This has produced a strange reality where every year organizations spend more and yet credential attacks keep rising.

A new authentication model is changing both sides of this equation. Wireless biometric passwordless authentication, delivered through hardware devices such as Token Ring and Token BioStick , is cutting login time, reducing workplace friction, eliminating identity-driven intrusions, and returning measurable productivity to the business.

For the first time a security technology not only protects the enterprise but produces a meaningful financial return from the first day it is deployed.

The Productivity Drain Hidden in Plain Sight

Very few organizations have ever calculated the real cost of slow authentication. A password here, a code there, a retry after a mistyped digit. Each moment feels trivial until you apply it across the entire workforce.

Today the average login consumes twenty two seconds. Employees authenticate about twenty times a day across internal systems, cloud platforms, VPNs, and security tools. Those twenty two second logins multiplied by twenty events equal 440 seconds per day.

That is more than seven lost minutes per employee per day for access they are already entitled to.

With an average labor cost of fifty dollars per hour, those wasted 440 seconds equal $6.11 in daily lost productivity. Over a year the total exceeds $1600 per employee.

This is not theoretical. This is the daily cost of passwords and app based MFA across every industry.

What Happens When Login Time Drops to Two Seconds

With Token’s wireless biometric authentication, the entire process collapses into a single fingerprint match. No password. No code. No prompt. No app. The average login falls from twenty two seconds to two.

This returns twenty seconds for every authentication. Over twenty daily logins that is 400 seconds of recovered productivity per person every day.

That is $5.56 returned per day.
That is $122.22 returned per month.
That is $1,466.67 returned each year.

And this is before considering the cost of password resets, which shrink to almost nothing once passwords disappear.

MFA ROI

Here is where the economics become impossible to ignore. Token devices are available in enterprise volumes as a subscription for under $100 per year.

When the organization gains nearly $1500 of productivity per employee, the return on investment approaches fifteen times the cost. Most CIOs, CISOs, and CFOs will never see another security technology with this kind of annual payback.

Security Strengthens at the Same Time

The productivity gains alone justify the transition to wireless biometric passwordless authentication. The security improvements drive the point home even further.

Token makes the common identity based attack paths disappear.

  • No passwords to steal.
  • No codes to intercept.
  • No push prompts to manipulate.
  • No shared secrets.
  • No judgment calls for the user.

Even the most advanced real time phishing kits fail because Token will not authenticate unless three conditions are met: the domain matches exactly, the user presents a live fingerprint, and the user is physically present next to the login device.

If an employee clicks a perfect phishing link, Token simply refuses to authenticate. If a threat actor calls the help desk pretending to be an employee to trigger a reset, they still cannot log in without the biometric fingerprint and the physical Token device. Even device theft is useless without the fingerprint.

The biggest ransomware events of the past year share the same root cause. Aflac, Ingram Micro, Hawaiian Airlines, Qantas and others were compromised through credential theft, MFA relay, or social engineering. Token collapses that attack surface. When credentials cannot be stolen or misused, attackers lose their easiest and most reliable entry point.

One prevented breach can offset the entire cost of the authentication platform for the next decade. Many organizations spend millions responding to incidents that would never occur if identity were properly locked down.

A New Era for Authentication Economics

Authentication has always been treated as a necessary inconvenience. It was slow, expensive, disruptive, and still vulnerable.

Token’s wireless biometric passwordless technology breaks this cycle completely. Login time drops to nearly zero. Credential theft collapses. Password resets disappear. The business regains more than fourteen hundred dollars per employee every year for a technology that costs under one hundred dollars per employee.

Token Ring and Token BioStick are the gold standard. Phishing-proof. Tamper-resistant. Biometrically bound. Proximity required.

This is the rare moment in cybersecurity where a stronger security control also produces immediate financial upside. It signals a shift toward identity technologies that simultaneously improve protection, streamline operations, and pay for themselves faster than any security investment in the past two decades.

The passwordless future has been promised for years.

Learn more about how Token is the first to deliver it in a form that is secure, wireless, biometric, phishing proof, proximity based, and economically undeniable at tokenring.com .

Sponsored and written by Token .

How Did Epstein Get Rich? The New York Times Investigates His "Scams, Schemes, Ruthless Cons"

Democracy Now!
www.democracynow.org
2025-12-17 13:49:25
As the Trump administration is expected to release investigative files related to Jeffrey Epstein later this week, a recent New York Times investigation delves into one of the biggest mysteries about the deceased sexual predator: how the college dropout with no financial training rose through the wo...
Original Article

This is a rush transcript. Copy may not be in its final form.

AMY GOODMAN : This is Democracy Now! , democracynow.org. I’m Amy Goodman, with Juan González.

Friday is the deadline for the Department of Justice to release its investigative files into the dead financier and serial sex trafficker Jeffrey Epstein. The deadline was set with the passage of the Epstein Transparency Act last month. One of the questions that’s remained largely unanswered until now is: How did Jeffrey Epstein become so extravagantly wealthy, wealth that both enabled his crimes and shielded him from scrutiny and accountability for so many years?

Well, a new investigation by The New York Times uncovered details about Epstein’s rise, previously unreported, and provides an answer. The investigation is headlined “Scams, Schemes, Ruthless Cons: The Untold Story of How Jeffrey Epstein Got Rich.” This is a video clip featuring some of the reporters. It begins with business reporter Jessica Silver-Greenberg.

JESSICA SILVER - GREENBERG : How did Jeffrey Epstein have the financial backing to abuse what turns out to be hundreds of young women and girls?

DAVID ENRICH : The hundreds of millions of dollars that Epstein amassed, the palatial estates and aircraft.

JESSICA SILVER - GREENBERG : Connections to some of the wealthiest, most established people all over the world. There’s been a tremendous number of conspiracy theories and myths.

DAVID ENRICH : From he was running a huge blackmail operation to he was affiliated with spy agencies.

JESSICA SILVER - GREENBERG : Through months of reporting and digging through documents.

DAVID ENRICH : People’s diaries, letters, old photo albums.

JESSICA SILVER - GREENBERG : The answer is: He stole it.

AMY GOODMAN : “He stole it.” The New York Times investigation begins with Epstein in his early twenties, a college dropout, teaching math at the prestigious Dalton High School here in New York. He’s introduced by a student’s father to Ace Greenberg, the future chief executive of Bear Stearns, an introduction that changed Epstein’s life.

For more, we’re joined by New York Times deputy investigations editor David Enrich, who co-wrote the new piece.

We thank you so much for being with us, joining us from Dobbs Ferry. Can you name names? Lay out Jeffrey Epstein’s rise, the critical importance of the people he connected with, and the lies, the thievery, all that you lay out, after, what, months, years of this investigation.

DAVID ENRICH : Yeah, we’ve spent a long time on this one. And it really starts at Bear Stearns, where Epstein is introduced to a guy named Ace Greenberg, who was a top executive at the investment firm. And Greenberg and another of his colleagues, Jimmy Cayne, who’s also a top executive there, took Epstein under their wings and made him their protégé.

And Epstein proceeded to go on kind of this spree of wrongdoing at Bear Stearns, everything from abusing his expense account, lying on his résumé, giving a girlfriend early access to kind of hot investment deals. And time and time again, Epstein’s protectors at the bank went to bat for him and basically got him out of trouble. And this basically — this was the start of a lifelong pattern for Epstein, where he would push the envelope, cross ethical, moral, sometimes legal lines, and basically escape with impunity because of his really astounding ability to charm people in positions of power and to use his leverage over people in positions of power.

And one of the things we heard about Bear Stearns was that he was — and this was a time in the late '70s and early ’80s where there was a lot of drugs and sex going on within the firm itself, and Epstein, it sounds like, was providing some of the top executives with drugs and with access to women. And so, you know, he had leverage, and he was not afraid to use the leverage. And again, we see this over and over and over again in the ensuing decades of Epstein's life and career.

JUAN GONZÁLEZ: And, David, one of the — one of the key figures that he cultivated was the Harvard law professor Alan Dershowitz. Could you talk about how they got together and the importance of Dershowitz in his rise?

DAVID ENRICH : Yeah, and Dershowitz is interesting, because he is both — he goes on to become Epstein’s kind of leading defender and leading protector, but Epstein connects with him through — by doing this thing that he does all the time, which is he leverages one connection to form another to form another.

And so, in the case of Dershowitz, Epstein, in the early '90s, had become close with a woman named Lynn Forester, who was this successful telecom executive who was very close to Bill Clinton and the Clinton White House. Epstein befriends her. She is friends with Dershowitz, and Forester asks Epstein if — or, I'm sorry, asks Dershowitz if Epstein can come over and visit him. So, Epstein and Dershowitz get together on Martha’s Vineyard, and Epstein convinces Dershowitz to fly out to Ohio with Epstein for a birthday party for Les Wexner, who is the billionaire retail tycoon who owns brands like Victoria’s Secret. And this is the start of a yearslong and very fruitful relationship for both Epstein and Dershowitz.

And Dershowitz gets a lot of notoriety and, I think, from his perspective, probably fame from his representation of Epstein. And Epstein, for his part, gets this access to a world-class lawyer, who engineers a sweetheart deal for him in around 2007 that gets him, basically, out of trouble when he was facing a sex trafficking and money laundering investigation in Florida. And Dershowitz, I mean, to this day, is one of Epstein’s leading public defenders. And so, it was an investment that Epstein made in this man in a very kind of prescient way early on. And that entailed not just introducing him to people, but also getting him access to invest in very exclusive hedge funds, and, when those investments didn’t work out, getting Dershowitz bailed out of those investments.

So, Epstein was just absolutely masterful at leveraging one connection to benefit another. And, you know, it’s often been said that Epstein is this math genius and this super sophisticated financier. What we found in our reporting is much simpler, which is that he may have been those things, but the evidence shows that what made a difference for him in the long run was his ability to charm and entrance and leverage powerful people off of one another.

AMY GOODMAN : And if you can talk about the connections, as we’re about to see the documents released, if we are, Friday, December 19th, the connections to Trump, to Robert Maxwell, the father of Ghislaine Maxwell, to Ghislaine Maxwell herself, serving a 20-year sentence for —

DAVID ENRICH : Yeah.

AMY GOODMAN : — sex trafficking? Go ahead, David.

DAVID ENRICH : Well, and we don’t know what’s going to be in these files, if indeed there are files released by Friday. And I think it is much more likely — I don’t think it’s very likely that we’re going to see a lot of stuff that kind of plumbs through Epstein’s ancient history, the way we did in this article. That’s part of the reason we wanted to do this reporting, was to provide — kind of shine a light on a phase in his life that has not undergone quite as much scrutiny as his later years.

And I think what we’re likely to see in these files is quite a bit about him in the 2000s, essentially, and in the 2010s. And that happens to be a period where he certainly overlapped with Donald Trump for a period, he overlapped with Bill Clinton for a period, and that there are a lot of powerful, important figures kind of darting in and out of his life. And, obviously, there is an enormous amount of interest, rightly so, in what these files show, if anything, about how Epstein’s sex trafficking operation ensnared some of these kind of boldfaced names.

The truth is — and I’m not trying to be coy or evade the question — we just really have no idea what is in these files and what is going to actually be released in a way that is legible. And I think there is an expectation or a concern that these might be very, very heavily redacted, if they get released at all. And hopefully I’m wrong about that, because I think the whole world is clamoring for some transparency here. And just as someone who’s been covering this for like six years, six-plus years now, with my colleagues at the Times , we are really eager to see what’s in these files.

AMY GOODMAN : And finally, what surprised you most as you investigated him for all of these years? We just have 30 seconds.

DAVID ENRICH : I think what surprised me the most was just how pedestrian some of his scams were. This is not someone who was hatching this, like, extremely elaborate plot to con sophisticated people through all these, like, bells and whistles. He was just grabbing people’s money and running with it. And for all of the attention that’s been paid to the possibility of Epstein being part of spy services or running this really sophisticated blackmail operation, the truth that we found — and there may be more to it, but what we found — was much more run-of-the-mill and kind of low-level than that.

AMY GOODMAN : David Enrich, we want to thank you for being with us, deputy investigations editor for The New York Times . We’ll link to your new investigation , “Scams, Schemes, Ruthless Cons: The Untold Story of How Jeffrey Epstein Got Rich.”

Happy birthday to Jeff Stauch! And happy belated birthday to Renée Feltz! I’m Amy Goodman, with Juan González. Thanks for joining us.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

The original Mozilla "Dinosaur" logo artwork

Lobsters
www.jwz.org
2025-12-17 13:38:51
Comments...
Original Article
4Ø3
NO ROBOTS
4Ø3

Chile's Trump? Ariel Dorfman on the Election of Pinochet Admirer José Antonio Kast

Democracy Now!
www.democracynow.org
2025-12-17 13:33:15
José Antonio Kast has won Chile’s presidential election, with the far-right leader getting about 58% of the vote in Sunday’s runoff against Jeannette Jara, a member of the Communist Party who served as labor minister under outgoing President Gabriel Boric. Kast has openly praised former ...
Original Article

This is a rush transcript. Copy may not be in its final form.

AMY GOODMAN : This is Democracy Now! , democracynow.org, The War and Peace Report . I’m Amy Goodman, with Juan González.

We turn now to Chile, looking at the election of José Antonio Kast, who’s set to become Chile’s most right-wing leader since the U.S.-backed dictator Augusto Pinochet. In Sunday’s election, Kast won about 58% of the vote, defeating Jeannette Jara, a member of the Communist Party. She had served as labor minister under outgoing Chilean President Gabriel Boric, who was not eligible to run for reelection. Kast once praised Pinochet, saying, quote, “If he were alive, he would vote for me,” unquote. On Tuesday, Kast traveled to Buenos Aires to meet with Argentina’s far-right President Javier Milei.

We go now to Santiago, where we’re joined by Ariel Dorfman, the acclaimed Chilean American novelist, playwright, essayist, academic and human rights activist, distinguished professor emeritus of literature at Duke University in North Carolina. Ariel Dorfman served as a cultural adviser to Salvador Allende from 1970 to 1973. After the U.S.-backed military coup that installed dictator Augusto Pinochet, Ariel Dorfman fled Chile and went into exile. Today he’s recognized as one of Latin America’s greatest writers. His essays, novels, poems, plays have been translated into more than 40 languages. And he has a new article in The New York Times headlined “Chile’s Election Is More Than Just a Swerve to the Right.”

Thanks so much for being with us, Ariel Dorfman. Explain the significance of Chile’s election today.

ARIEL DORFMAN : Well, thank you so much for having me, Amy, and it’s a pleasure to be on Democracy Now! , especially when democracy now is in such danger in Chile and around the world.

There has been since — since democracy was restored in 1990, we have had, basically, center-left governments, except for two occasions, which was of Sebastián Piñera. And Sebastián Piñera twice was elected president, but he could be understood as a moderate conservative. What made it possible for him to be elected in Chile over these 35 years, eight years of the 35 years, is that he voted against Pinochet remaining in power in the referendum of 1988.

In that referendum of 1988, a young, 22-year-old student called José Antonio Kast appeared on television saying how he adored the general and hoped that he would remain in power forever. Now that same man, who since then has accumulated a series of more outrageous statements still, is going to be the next president of this country. In other words, a land that got rid of General Pinochet, that danced in the streets when Pinochet died in 2006, that man is now going to be the president of this country.

It is a political and ethical earthquake, because there are — I mean, I can just go on and on about what this man means. He is going to assault the network that has been constructed, not in the last 35 years, but in the last hundred years, the economic and social rights of workers, the Indigenous rights. He’s against abortion even if the mother’s life is in danger. He’s against gay couples, obviously.

I could just go on and on and on about this man, whose father, by the way, was a Nazi himself. He was — in 1942, joined the Nazi Party as an officer in the Wehrmacht of Germany. And then, he, under false papers, arrived in Chile. So, it’s very strange, you know, because Kast has based his campaign on an anti-immigrant agenda, and according to that agenda, his father would be expelled right now, because he arrived undocumented to Santiago.

JUAN GONZÁLEZ: Well, but, Ariel, to what do you attribute the majority of the Chilean people voting for him? And also, to what degree do you think he’ll be able to implement that program? He still needs support in the Chilean — in the Chilean government, as well, among the elected deputies of that country.

ARIEL DORFMAN : So, let’s go first to your first question, which is — by the way, he won 58%, not 50%, of the vote, 58%, which is an enormous majority in Chile, more than 16 points more than Jeannette Jara, who was his adversary. But the point about this is that the major problems that Chileans constantly are speaking about is too much immigration, enormous amount of crime, though the crime is not linked to immigrants, as the right wing will say — it’s mostly Chileans against Chileans, but it doesn’t matter; that’s their message, and people are buying it — and the problem of affordability. But, you know, Kast would not be able to have this victory, this significant victory, in which a series of people who are not necessarily against democracy want security in their lives — they want somebody strong, like Bukele in El Salvador, in fact, you know, because that’s one of the things. Kast has had advisers from Bukele, the Salvadorian despot, to build maximum-security prisons here and do away, basically, with habeas corpus and other forms of democratic institutions. So, Kast would not have been able to fill this void if the center-left had not, over many, many years, in some senses, turned its back on the troubles of the people.

I want to mention here, because I think I had mentioned this before when I spoke about coming on the program, in my novel The Suicide Museum , there’s a long section, several chapters, on the year 1990. All of it happens in the year 1990, which is the year of the transition from dictatorship to democracy. And I focus on the moment when Allende, Salvador Allende, is taken from his anonymous tomb and given a state funeral in Santiago. I was there. I was part of that. I was living there at the moment. And what called my attention, and I mentioned in the novel The Suicide Museum , is that the elite was inside the cemetery and in the cathedral where Allende was being buried, but all the people, the young people, the women, the workers, the peasants, the students, everybody who had given their lives and fought for 17 years against Pinochet, those people were left outside. They were even tear-gassed. In other words, because they wanted also to give a homage to their president, their dead president, the people who had made it possible for Allende to be buried in democracy, for democracy to be returned to Chile, were sort of left out. I found this symbolic.

It’s not that in 35 years many good things were not done. You know, poverty was diminished significantly. Infrastructure was major. Major things were done in Indigenous rights. Major things were done in sexual rights and reproductive rights. So, there have been very, very big advances in that sense. But it’s been insufficient. And I think that there is a need for the center-left and the left, in general, to look very carefully at what blindness or mistakes or fractures they have allowed in the past, and ask themselves what they need to do to reimagine the country in a different way, to think of the country as a different project.

You know, I found that — one of the things that I found in Chile this last month and a half that we’ve been here is there’s a sense where people are detached. They’re uneasy. I call it ” malestar ” in my article in today’s New York Times , malestar meaning they don’t feel well with themselves. They’re a bit sick. They’re a bit unhinged. They don’t feel that things are going well. And so, of course, they’ll say, “Well, somebody offers us security. They offer us a clear solution, even if it means, you know, getting rid of some democratic institutions. Well, let’s be secure at last. Let’s not have criminals roaming the streets.” I hardly know of anybody who has not had some sort of assault, a criminal assault of some sort, not all narcotrafficking, but a lot of that, right?

So, people are fed up with that and tired of that, and the left has not given them a solution. And this is not, I think, only the case in Chile. I think it’s the case worldwide. The rise of authoritarianism is only possible because we, who want a just and equal society, who do not want to continue with exploitation and super millionaires deciding everything for us, and climate apocalypse — because Kast, of course, is getting rid of all the watchdogs on climate, climate change, right? We want, and we want to make sure, that those people who are decent, progressive people, and who are, I think, the great majority, find a way of expressing themselves in something that inspires, inspires the people. I don’t find my people here inspired. I find them angry, confused, sad, with malestar , with that sense of unease and malaise everywhere almost, right?

There’s still — you know, there’s still a great deal of joy in the people. But I think that in the referendum of 1988, the people of Chile, in the worst circumstances, they managed to defeat the dictator, even if the dictator had — this is the one where Kast was for Pinochet, and Piñera, the moderate conservative, was against him. In that election, the people of Chile rejected that, that possibility of Pinochet staying in power. And that is why I have some hope, as well. I feel as if that joy was demobilized. That struggle, that sense of participation, of protagonism, that was possible all during the dictatorship, from 1988 especially until 1990, it was stopped. In some sense, it was said, “Go home, produce, consume, be happy, and just leave the governing to us,” instead of saying, “Let’s continue the mobilization.” You know, when Pinochet was commander-in-chief during — in democracy even, he put his troops on alert, because he was being investigated. Instead of calling the people into the streets and saying, “We are stopping this country. Stop it. You’re not in charge, General Pinochet, anymore,” they said, “Go home. Don’t worry. We’ll take care of things.” So, it’s been compromise after compromise, and it’s been too many. And I think people, therefore, are uninspired, basically. And if you have an uninspired left, an uninspired people, they will tend to — the void will happen in that sense.

You know, I have a metaphor for this, by the way. The reason why I think that Kast is in trouble and may be in trouble in the future, first of all, I think he’s not going to be able to put into his — he wants to get rid of hundreds of thousands of civil servants, because they’re parasites, according to his adviers. He wants to deport 330,000 undocumented immigrants. He wants to build a wall, of course. I mean, he wants to finish with all the transgender rights and the gay rights and the women’s rights, a series of things. But apart from that, it turns out that he wants to erase the country’s history. He wants to get rid of the story of what the coup was about and what the coup engendered. He wants his hero, Pinochet, once again to be venerated by all. He wants to forget the concentration camps and the executions and the torture and the exiles and all the terrible things that have been memorialized in this time.

I think that there’s a saying — I like this saying. I was thinking of it. I was thinking about Kast, you know? It says — an African proverb says, “The ax forgets, but the tree remembers.” And I think this is true in Chile. I think the dead of Chile remember. I think the survivors of Pinochet remember. I think many people in Chile remember. I think — I mean, I know this is. I mean, I’m a writer. I’m a novelist. I’m a poet. So I think there’s a lyrical sense to this, which is, the Kast presidency will be haunted by what it tries to suppress. It will come out from all the trees of Chile. I think Chile is a forest of resistance.

We are a minority now for the moment. We are taking our time. It’s 42%. It can be more. It doesn’t matter how many you are, really. It matters that in the streets, people will not allow a regression of this sort. And if Kast wants to throw the army into this to try to repress the people, as happened in the past, because the story of Chile is a story of massacres of peasants and workers and students for a hundred years now — if Kast wants to do that, he may find that there is a recalcitrant army. The army already went through the shame of having been the pawn of Pinochet’s dictatorship. They do not want it anymore. And when there was the estallido , the explosion of hundreds of thousands of Chileans who were fed up, this time from the left, let’s say — right? — and almost brought down the government, Piñera, who was then president, before Boric, Piñera asked the armed forces to police the streets, and the general in charge of the armed forces says, “We are not policemen. That is not what we do.” And this is a very big change, right?

So, let us see what’s going to happen as Piñera — as Kast tries to impose a neoliberal model on a country that has, in fact, in the polls, constantly said that it’s against so many millionaires having so much money, so much inequality, so much injustice. But people want control over their lives.

AMY GOODMAN : Ariel —

ARIEL DORFMAN : And they can’t have control over their lives if they feel that there’s a security threat next door to them and that things will happen which they can’t control their own neighborhoods, in that sense, right?

AMY GOODMAN : Ariel, we have 20 seconds.

ARIEL DORFMAN : So, we’re up against a very special moment — I’m sorry, yes.

AMY GOODMAN : I want to thank you so much for being with us, Ariel Dorfman, acclaimed Chilean American writer. We’re going to link to your New York Times op-ed , “Chile’s Election Is More Than Just a Swerve to the Right.”

Coming up, “Scams, Schemes, Ruthless Cons: The Untold Story of How Jeffrey Epstein Got Rich.” Stay with us.

[break]

AMY GOODMAN : “Antipatriarca,” “Anti-patriarchy,” by the Chilean musician Ana Tijoux, performing in our Democracy Now! studio.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Learning the oldest programming language (2024)

Hacker News
uncenter.dev
2025-12-17 13:25:06
Comments...
Original Article

(last edited ) ·

While I probably should be learning a language like C, Go, or whatever new trendy language the ThePrimeagen mentions on Twitter (OCaml?), I'm going to attempt to learn Fortran [1] .

A quick history

Fortran, which stands for FORmula TRANslator [2] , was created at IBM by John Backus in 1957 for scientific applications and has apparently been popular for high-performance computing and benchmarking supercomputers in recent years. Fortran has had several subsequent releases since then; FORTRAN 77, Fortran 90, Fortran 95, Fortran 2003, Fortran 2008, and the latest Fortran 2018.

Which version of Fortran?

To understand what version of Fortran to learn/use, we first must understand the difference between fixed form and free form Fortran. The fixed form layout comes from the very beginning of Fortran, inherited from punch cards, and has odd restrictions about the column in which comments and statements are placed. The free form layout, first introduced in Fortran 90, removed special columns and added the ability to write comments wherever, and is what we'll be learning in this article. The compiler we'll be using is GNU Fortran, or gfortran . You can install it via Homebrew (macOS) with the gcc formula, or install it using a package manager for your OS . To tell gfortran that your code uses the free form layout, set the file extension to .f90 or newer. The following comment on the Fortran discussion board explains this well.

The .f90 suffix means that the source code is free format, not that
the code conforms to the Fortran 90 standard. Code that uses the .f90
suffix can use features from any Fortran standard. All Fortran
compilers recognize .f90 as a suffix indicating free source form, but
some may not recognize a suffix such as .f95, .f03, .f08, or .f18.
Some users may have build tools that do not recognize suffixes other
than .f90. Most Fortran source code on GitHub that uses features from
a standard more recent than Fortran 90 still uses the .f90 suffix.

Understanding the syntax

Coming from TypeScript, and before that, Python, I'm very used to (and comfortable with) modern — you might say "aesthetic" — syntax . Although I wouldn't say Fortran syntax is quite modern , it seems to avoid the syntactic sugar nightmares that plague beginners in other languages [3] . Take a look at this helloworld.f90 example below.

program helloworld

  print *, 'Hello, world!'

end program helloworld

Older Fortran programs required the use of SCREAMING_CASE for all keywords, but in modern Fortran you can and it is recommended to use snake_case (you can still use SCREAMING_CASE or any other case you want though).

Just from this small example we can gather that...

  • Every Fortran program begins with program <program-name> and ends with end program <program-name> .
  • To display text on the terminal we use print *, '<message>' .

The syntax for printing is a little funky though. What is that asterisk doing there? The asterisk, aside from being used as a mathematical operator, indicates the "default". So for print , * means "print to the default output channel" (or "print to the default output file unit" to be precise), which is typically going to be STDOUT.

I can't find exactly where this is documented but you don't actually need the start and end program <program-name> ; you could write a hello world program like this, though as I just mentioned this doesn't seem to be a common practice and isn't really very useful in any practical scenario.

print *, 'Hello, world!'; end

Here's another, slightly more complicated example.

program calculator
  implicit none

  real :: x, y, answer
  character(1) :: choice

  print *, 'x:'
  read *, x
  print *, 'y:'
  read *, y

  print *, '+, -, *, /:'
  read *, choice
  if (choice == '+') then
    answer = x + y
  end if
  if (choice == '-') then
    answer = x - y
  end if
  if (choice == '*') then
    answer = x * y
  end if
  if (choice == '/') then
    answer = x / y
  end if

  print *, 'Answer:', answer

end program calculator

Starting right at the top, we have something new: implicit none . Added in Fortran 90, implicit none disables implicit typing defaults and all variables must be explicitly declared. In Fortran, implicit typing is the practice of assigning default types to variables based on the character a variable name begins with. Variables starting with I through N are INTEGER s, everything else is REAL . It is "a legacy of the past" and usage of an implicit none statement is "strongly advised" ( implicit none - Fortran Wiki ).

A common Fortran joke goes along the lines of “GOD is REAL, unless declared INTEGER" [4] because of implicit typing!

Moving on, we declare our first variables in this program.

real :: x, y, answer
character(1) :: choice

Here we are declaring x , y , and answer with the REAL type, and choice with the CHARACTER type. The REAL type stores floating point numbers [5] , and CHARACTER ... stores characters.

Next, we prompt the user for our x and y values.

print *, 'x:'
read *, x
print *, 'y:'
read *, y

Notice how we can take input from the user with read and assign it to a value with the read *, <variable> syntax. The asterisk here means read from the default input channel/file unit, which would be STDIN.

We do the same for prompting the user to select an operation.

print *, '+, -, *, /:'
read *, choice

Finally, we use a series of basic if-statements to calculate our answer and display it in the terminal.

if (choice == '+') then
  answer = x + y
end if
if (choice == '-') then
  answer = x - y
end if
if (choice == '*') then
  answer = x * y
end if
if (choice == '/') then
  answer = x / y
end if

print *, 'Answer:', answer

If we run this, we- wait. Did I even tell you how to compile a Fortran program yet?

How do I actually run this?

First, compile our calculator program with gfortran -o calculator calculator.f90 . Then you can run it with ./calculator . If you only instruct gfortran of the input file ( gfortran calculator.f90 ), the default output executable will be named a.out .

Let's run our program now.

$ gfortran -o calculator calculator.f90
$ ./calculator
 x:
10
 y:
2
 +, -, *, /:
*
 Answer:   20.0000000

Pretty cool, huh?

A few improvements

Our calculator isn't perfect yet though. What if the user tries to divide by zero?

 x:
10
 y:
0
 +, -, *, /:
/
 Answer:         Infinity

Probably not the answer you expected. Let's try to fix that.

if (choice == '/') then
  if (y /= 0.0) then
    answer = x / y
  else
    print *, 'Error: Division by zero is not allowed.'
	stop
  end if
end if

Here we use the inequality operator, /= , to check if the y value is zero. Now, if the user tries to divide by zero, we'll print an error message and use the stop statement to end the program.

Great. We got rid of the zero division mess, but our code isn't pretty at all. Who wants a bunch of if statements? We can simplify this using the select case statement (also known as the case statement).

select case (choice)
  case ('+')
    answer = x + y
  case ('-')
    answer = x - y
  case ('*')
    answer = x * y
  case ('/')
    if (y /= 0.0) then
      answer = x / y
    else
      print *, 'Error: Division by zero is not allowed.'
      stop
    end if
  case default
    print *, 'Invalid choice. Please choose +, -, *, or /.'
    stop
end select

This also has the handy benefit of telling the user if they made an invalid choice while selecting the operation.

That’s just a quick introduction to a few modern Fortran features: declaring variables, printing and reading to and from the terminal, if and select case , and stop . Next time, we’ll talk more about where Fortran is actually used, cooler things you can build with it, and how the Fortran language & community are rapidly modernizing!


  1. Ironically, in the ~3-ish months since I started writing this article, ThePrimagen has recently said he "take[s] back everything i said about FORTRAN" — apparently having some interest in the language! ↩︎

  2. According to sources listed on Fortran's Wikipedia , the name might also have stood for Formula Translating System or just Formula Translation . ↩︎

  3. See The Rust programming language absolutely positively sucks : r/rust and Rust is a nightmare to learn coming from Java - community - The Rust Programming Language Forum . ↩︎

  4. The first letter of "GOD", a "G", is not within I through N and is therefore of the REAL type ("GOD is REAL"). ↩︎

  5. You can also use double precision for larger (more precise) floating point numbers. ↩︎

Matthew Garrett: How did IRC ping timeouts end up in a lawsuit?

PlanetDebian
mjg59.dreamwidth.org
2025-12-17 13:17:23
I recently won a lawsuit against Roy and Rianne Schestowitz, the authors and publishers of the Techrights and Tuxmachines websites. The short version of events is that they were subject to an online harassment campaign, which they incorrectly blamed me for. They responded with a large number of defa...
Original Article

I recently won a lawsuit against Roy and Rianne Schestowitz, the authors and publishers of the Techrights and Tuxmachines websites. The short version of events is that they were subject to an online harassment campaign, which they incorrectly blamed me for. They responded with a large number of defamatory online posts about me, which the judge described as unsubstantiated character assassination and consequently awarded me significant damages. That's not what this post is about, as such. It's about the sole meaningful claim made that tied me to the abuse.

In the defendants' defence and counterclaim [1], 15.27 asserts in part The facts linking the Claimant to the sock puppet accounts include, on the IRC network: simultaneous dropped connections to the mjg59_ and
elusive_woman accounts. This is so unlikely to be coincidental that the natural inference is that the same person posted under both names
. "elusive_woman" here is an account linked to the harassment, and "mjg59_" is me. This is actually a surprisingly interesting claim to make, and it's worth going into in some more detail.

The event in question occurred on the 28th of April, 2023 . You can see a line reading *elusive_woman has quit (Ping timeout: 2m30s) , followed by one reading *mjg59_ has quit (Ping timeout: 2m30s) . The timestamp listed for the first is 09:52, and for the second 09:53. Is that actually simultaneous? We can actually gain some more information - if you hover over the timestamp links on the right hand side you can see that the link is actually accurate to the second even if that's not displayed. The first event took place at 09:52:52, and the second at 09:53:03. That's 11 seconds apart, which is clearly not simultaneous, but maybe it's close enough. Figuring out more requires knowing what a "ping timeout" actually means here.

The IRC server in question is running Ergo (link to source code ), and the relevant function is handleIdleTimeout() . The logic here is fairly simple - track the time since activity was last seen from the client. If that time is longer than DefaultIdleTimeout (which defaults to 90 seconds) and a ping hasn't been sent yet, send a ping to the client. If a ping has been sent and the timeout is greater than DefaultTotalTimeout (which defaults to 150 seconds), disconnect the client with a "Ping timeout" message. There's no special logic for handling the ping reply - a pong simply counts as any other client activity and resets the "last activity" value and timeout.

What does this mean? Well, for a start, two clients running on the same system will only have simultaneous ping timeouts if their last activity was simultaneous. Let's imagine a machine with two clients, A and B. A sends a message at 02:22:59. B sends a message 2 seconds later, at 02:23:01. The idle timeout for A will fire at 02:24:29, and for B at 02:24:31. A ping is sent for A at 02:24:29 and is responded to immediately - the idle timeout for A is now reset to 02:25:59, 90 seconds later. The machine hosting A and B has its network cable pulled out at 02:24:30. The ping to B is sent at 02:24:31, but receives no reply. A minute later, at 02:25:31, B quits with a "Ping timeout" message. A ping is sent to A at 02:25:59, but receives no reply. A minute later, at 02:26:59, A quits with a "Ping timeout" message. Despite both clients having their network interrupted simultaneously, the ping timeouts occur 88 seconds apart.

So, two clients disconnecting with ping timeouts 11 seconds apart is not incompatible with the network connection being interrupted simultaneously - depending on activity, simultaneous network interruption may result in disconnections up to 90 seconds apart. But another way of looking at this is that network interruptions may occur up to 90 seconds apart and generate simultaneous disconnections[2]. Without additional information it's impossible to determine which is the case.

This already casts doubt over the assertion that the disconnection was simultaneous, but if this is unusual enough it's still potentially significant. Unfortunately for the Schestowitzes, even looking just at the elusive_woman account, there were several cases where elusive_woman and another user had a ping timeout within 90 seconds of each other - including one case where elusive_woman and schestowitz[TR] disconnect 40 seconds apart . By the Schestowitzes argument, it's also a natural inference that elusive_woman and schestowitz[TR] (one of Roy Schestowitz's accounts) are the same person.

We didn't actually need to make this argument, though. In England it's necessary to file a witness statement describing the evidence that you're going to present in advance of the actual court hearing. Despite being warned of the consequences on multiple occasions the Schestowitzes never provided any witness statements, and as a result weren't allowed to provide any evidence in court, which made for a fairly foregone conclusion.

[1] As well as defending themselves against my claim, the Schestowitzes made a counterclaim on the basis that I had engaged in a campaign of harassment against them. This counterclaim failed.

[2] Client A and client B both send messages at 02:22:59. A falls off the network at 02:23:00, has a ping sent at 02:24:29, and has a ping timeout at 02:25:29. B falls off the network at 02:24:28, has a ping sent at 02:24:29, and has a ping timeout at 02:25:29. Simultaneous disconnects despite over a minute of difference in the network interruption.

Hackers access Pornhub’s premium users’ viewing habits and search history

Guardian
www.theguardian.com
2025-12-17 13:16:40
ShinyHunters group reportedly behind the hack affecting data of 200m users thought to be from before 2021 Hackers have accessed the search history and viewing habits of premium users of Pornhub, one of the world’s most popular pornography websites. A gang has reportedly accessed more than 200m data ...
Original Article

Hackers have accessed the search history and viewing habits of premium users of Pornhub, one of the world’s most popular pornography websites .

A gang has reportedly accessed more than 200m data records, including premium members’ email addresses, search and viewing activities and locations. Pornhub is a heavily used site and says it has more than 100m daily visits globally.

The hack was reportedly carried out by a western-based group called ShinyHunters, according to the website BleepingComputer , which first reported the hack. The site reported that the data included premium members’ email addresses, search and viewing activity and location. The data consists of 201m records related to premium members.

The website added that the Canadian-owned Pornhub had received an extortion demand from ShinyHunters about the hack. The Reuters news agency on Wednesday also claimed to have spoken to a ShinyHunters member in an online chat who was demanding a payment in bitcoin to prevent the publication of data and delete it.

Pornhub said in a statement on its website that premium users had been affected by an attack on Mixpanel, a company that had provided data analytics to the publisher. Pornhub said a “select” number of users had been affected and that it had stopped working with Mixpanel in 2021, indicating the data is not recent.

“It is important to note this was not a breach of Pornhub Premium’s systems. Passwords, payment details and financial information remain secure and were not exposed,” said the pornography service.

Pornhub added that an “unauthorized party” had been able to extract a “limited set of analytics events for some users”. Other types of data taken include video URL, video name, keywords associated with the video, and the time the event occurred, according to BleepingComputer.

In a statement Mixpanel said it was “aware” of the alleged data theft but said it had found no indication that it was related to a cyber-attack on the business last month.

Sophos, a cybersecurity firm, told the Guardian it had seen no evidence of Pornhub data being released on so-called leak sites – part of a hacking group’s armoury for extracting payments – or in online chat platforms linked to the ShinyHunters group.

Sophos said the ShinyHunters group was generally comprised of native English speakers in their late teens to early 20s and was part of a broader community of cyber criminals dubbed The Com, short for The Community. The Com is the same community from which the English-language speaking Scattered Spider group emerged, and which has been strongly linked with hacks against M&S, the Co-op and Harrods.

Pornhub and Mixpanel have been approached for comment.

A Path to WWIII? Greg Grandin on Venezuela, Trump's "Madman Doctrine" & More

Democracy Now!
www.democracynow.org
2025-12-17 13:15:19
President Trump has ordered what he called a “total and complete blockade” of sanctioned oil tankers entering and leaving Venezuela, as the United States escalates pressure on the government of President Nicolás Maduro. The move comes amid a major U.S. military buildup in the region and ...
Original Article

This is a rush transcript. Copy may not be in its final form.

AMY GOODMAN : President Trump has ordered a “total and complete blockade” of sanctioned oil tankers entering and leaving Venezuela, as the U.S. ramps up pressure on the government of Nicolás Maduro. The blockade comes amidst a major U.S. military buildup in the region and days after the U.S. seized an oil tanker filled with Venezuelan oil.

In a post on Truth Social, Trump wrote, quote, “Venezuela is completely surrounded by the largest Armada ever assembled in the History of South America. It will only get bigger, and the shock to them will be like nothing they have ever seen before,” unquote.

Since September, the U.S. military has also carried out at least 25 airstrikes on alleged drug boats, without offering evidence, in the Caribbean and eastern Pacific near Venezuela, killing at least 95 people.

On Tuesday, Vanity Fair published excerpts of bombshell interviews with Trump’s Chief of Staff Susie Wiles, in which she suggested the aim of the boat strikes is to topple Maduro. Wiles said, quote, “[Trump] wants to keep on blowing boats up until Maduro cries uncle. And people way smarter than me on that say that he will,” unquote.

On Tuesday, President Maduro denounced the U.S. actions.

PRESIDENT NICOLÁS MADURO : [translated] We tell the people of the United States our truth, and it is very clear: Imperialism and the Nazi-fascist right wing want to colonize Venezuela to take our wealth — oil, gas, gold, iron, aluminum and other minerals. We have sworn to defend our homeland. And in Venezuela, peace will always prevail, along with stability and shared happiness for our people.

To the people of the United States, we say again and again, one and a thousand times: [in English] No blood for oil! No war for oil!

[translated] The claims about drug trafficking are fake news, a lie, an excuse. Since they cannot accuse us of weapons of mass destruction, chemical weapons or nuclear missiles, they invent another pretext to create another Afghanistan, another Libya. And with moral authority and with God’s blessing, I say: [in English] No more Vietnam! No more Afghanistan! No more Libya! No more Iraq! No more war eternal! No! No! No! Enough!

[translated] We know we are morally and spiritually in the right.

AMY GOODMAN : We’re joined now by the Pulitzer Prize-winning historian, Yale University professor Greg Grandin. His latest book, America, América: A New History of the New World . He has a recent piece in The New York Times headlined “Trump’s Dated Strategy Is Putting Us on a Path to World War III .”

Welcome back to Democracy Now! , Professor Grandin. Can you start off by responding to what’s happening right now? We are doing this broadcast before President Trump makes his address to the nation tonight, unclear what that’s about. But talk about the latest developments with Venezuela.

GREG GRANDIN : Well, it is an unprecedented military buildup. It’s probably bigger than what the Spanish Empire sent to retake Spain in the 1820s in terms of sheer destruction — destructive force. And the classification of fentanyl as a weapon of mass destruction, and all sorts of presidential announcements that — you know, trying to lay a legal justification for this. And, of course, as this is going on, they’re still blowing up speedboats in the Caribbean and in the Pacific. And as you mentioned, Susan Wiles, the secretary — the chief of staff of Trump, said that this had nothing to do with narcoterrorism, that Trump actually doesn’t really care about narco drugs coming into the country; this is really just setting up and hoping to induce a regime change in Venezuela.

And Venezuela is really just the first, the first step. Marco Rubio, the secretary of state, from Florida, from South Florida, whose family itself is not uninvolved in drug trafficking, sees it in very ideological terms. He’s, you know, Cuban. And for whatever reason, they see Venezuela as the first step of finally bringing down the Cuban Revolution and bringing Cuba back into the orbit of the United States. And then, from there, of course, it’s Nicaragua. And we just saw this election in Chile, which I know you’re going to talk about later with Ariel Dorfman. But Latin America really is on a kind of knife’s edge between the left and the right. We see, in Argentina, Javier Milei and what the United States is willing to do to keep him in power, billions and billions of dollars, not just — not just through the Treasury Department, but also through the IMF , to prop up the peso. Honduras, there’s all sorts of machinations going on there in terms of the election that the U.S. was involved in.

And so, that really leaves Latin America divided, almost unprecedentedly divided. In the past, Latin America tended to be coherent and tended to be all dictatorships or all kind of center-left presidents. And now we have a continent that’s split angularly down the middle. And the image is quite stark. You have Brazil, and you have Mexico, and those are the two bulwarks of Latin America. And ultimately, if you’re going to get Latin America under control and back under the U.S.’s umbrella, you have to confront those two countries. Ultimately, that is the end goal.

And this is in the larger context of a dramatic reversal of U.S. foreign policy, the total renunciation of liberal internationalism. Now, liberal internationalism as an ideal, there was a big gap between in practice and as it actually functioned. But the idea was that the United States would superintend a world governed by common laws. The Trump administration announced in its National Security Strategy document, which it put out last week or a couple weeks ago, that the bipartisan consensus that came out of the Cold War has failed. And it had been essentially announced, implicitly, that what it sees as replacing it is a Monroe Doctrine for the entire world, that the way the United States acted with impunity to seize, to kill and to sanction, it could do anywhere.

AMY GOODMAN : Which brings us to what Secretary of Defense Pete Hegseth just said at the Reagan Defense Forum. He said, quote, “The Monroe Doctrine is in effect.”

DEFENSE SECRETARY PETE HEGSETH : After years of neglect, the United States will restore U.S. military dominance in the Western Hemisphere. We will use it to protect our homeland and access to key terrain throughout the region. We will also deny adversaries’ ability to position forces or other threatening capabilities in our hemisphere. Past administrations perpetuated the belief that the Monroe Doctrine had expired. They were wrong. The Monroe Doctrine is in effect, and it is stronger than ever under the Trump corollary, a commonsense restoration of our power and prerogatives in this hemisphere consistent with U.S. interests.

JUAN GONZÁLEZ: That was Defense Secretary Hegseth. I wanted to ask you, though, Greg — Latin America is not the same region that it was a hundred years ago or that it was 50 years ago. And when you mentioned this split in the region, I’m not so sure I agree with you on that. Brazil, Mexico and Colombia are the three largest nations in Latin America. They have half the population of the entire region, and all three of those countries are being led still by progressive, left-wing-oriented presidents. None of them are going to back a U.S. invasion, not to mention some of the smaller countries like Cuba or Nicaragua. And so, we’re in a situation where the United States is trying to impose a past that no longer exists. I’m wondering what you think, even if the intervention were to occur, and it seems likely that’s going to happen just in time to eclipse any news of the release of the Epstein files. The ability of the United States to impose its chosen leader on Venezuela is going to be severely restricted, not only by the international condemnation, but also by the fact that the Venezuelan military has been politicized directly, over years now, as a result of the Chávez revolution, so they’re not likely just to lay down their arms and allow the U.S. to come in. I’m wondering your thoughts.

GREG GRANDIN : Yeah, I agree with you completely. And that’s what I meant, that the region was split, and that in Mexico and Brazil, if you don’t — if they’re not — if they’re not isolated, then there is no kind of broader U.S. hegemony over the region, and certainly Colombia also, although there’s elections coming up in Colombia, and that country is going to be in play. But I think Mexico and Brazil are secure for now.

But, yes, and speaking about Venezuela, it’s unclear what the actual action is going to be. I mean, just stopping — just the sanction and blockade on the oil tankers are going to put enormous pressure on Venezuela to — you know, in terms of food, in terms of being able to import food and feed its people, and what that — and what kind of disaster that’s going to be. The sanctions are already incredibly punishing. There was bipartisan consensus going back decades, even to Obama. We might see some massive show of force, some targeted strikes. But you’re absolutely right, Venezuela is not Libya. It’s not going to collapse. I think there is — I think there is a kind of embedded structure, that, on the one hand, there is a radicalized sector of the population; on the other hand, there are — you know, there are people invested in a kind of militarized corruption that does structure some of the ways the country is governed. And Maduro could or could not go, but that doesn’t necessarily mean the United States is going to have its way and just be able to install a puppet like it did in Chile in ’73 or Guatemala in ’54, any number of coups in the past.

It’s a dangerous game. I was sitting out in the waiting room today, just now, a second ago, and CNN talked about a second near-crash between a private jet and some U.S. military force. I mean, they’re really — they’re really pushing it to the max. You know, of course, these murders on the high seas. Now we have the admission from the administration that this is just — you know, this has nothing to do with drugs; it has everything to do with Maduro. You know, these are innocent people. You know, it’s like — he’s like the Red Queen in Alice . You know, you execute, then you have the trial, and then you have the conviction, and then you have the trial. You know, he does everything backwards. We’re living in like an Alice in Wonderland foreign policy in Latin America.

But Latin America is confused, you know? There’s tension within Latin America. Petro said that he wouldn’t shake President-elect Kast’s hand, this is a Nazi. And he was immediately rebuked by Boric, you know, a center-leftist. So there’s also a lot of tension within Latin America about how to respond to the United States. That kind of — that kind of unity that existed coming out of the 2000s, Chávez, when Chávez was president, and Lula was the president of Brazil, and you had Kirchner in Argentina, and you had Bachelet in Chile, and, you know, it was a very — it was a very rhetorically strong and dominant form of social democracy that really commanded the rhetorical field. I think what we’re seeing here is a lot of — a lot of confusion about how to deal with Trump, just like the rest of the world. You know, it is, in some ways, the madman doctrine of diplomacy, except the madman doctrine was supposed to be a performance, an act, but we actually have a madman in the White House, in some ways.

JUAN GONZÁLEZ: Well, but this whole — the issue is, clearly, the key aspect of this in Venezuela, that distinguishes Venezuela from all the other governments in the region that Trump may not like, is these vast oil reserves.

GREG GRANDIN : Yeah.

JUAN GONZÁLEZ: On the one hand, could you talk about the importance of these oil reserves, and also the fact that the American people, by and large, all the polls indicate they have no interest in the United States launching a war against Venezuela, because Venezuela has not posed any threat to the United States?

GREG GRANDIN : Yeah, and that’s interesting. And so, I think that’s one of the reasons why it’s taking Trump so long to know — to figure out what to do. He may be a madman, but he’s not completely irrational. He does calculate. And there is obviously no bloodthirst within the rank and file of the Trump administration for a ground war in Venezuela, and certainly not within the country as a whole, and so he’s responding to that. Then there’s the calculus of, well, distraction, the Epstein files. Will this distract, or will people make the connection that we’re doing it to distract? You know, there’s a lot of independent — we’ve heard about how the Republican ecosphere, information sphere, is kind of fracturing and coming apart and eating each other.

Venezuela does have oil, but, you know, there’s lots of ways of getting Venezuela’s oil. I mean, Maduro has basically offered it up. Chevron, as we speak, is pumping oil and sending it to Port Arthur in Texas to be processed. And there’s lots of ways to make — get control. So, a war with Venezuela over oil is an ideological war, and it’s led by the Marco Rubio faction, the war party within the Trump administration, that sees Latin America in very ideological terms, in which Venezuela is the step — is the first step to contain a left, a left that, yes, is still strong and still, you know, has quite a purchase. I mean, even in Chile — right? — 42% of the population voted for a communist woman, in one of the most socially conservative countries in Latin America. That’s not nothing. I mean, it’s a shame we got the Nazi, but, you know, 42% of the country voted for Jeannette Jara, who is, you know, a communist woman. That speaks, I think, to the strength of — the ongoing strength of the left.

But there isn’t a coherent strategy of how to deal with the United States. I mean, any country going to come to Venezuela’s aid to try to get the oil out? I don’t think Colombia can risk that. You know, there are ways in which you can imagine Colombia trying to get Venezuela’s oil out of there, but do they want to provoke the United States to that degree? It’s a little unclear. So, I think everything’s up in the air and on the table at this moment. Anything can happen. And I guess we’ll — things will be clarified by the speech, or not.

AMY GOODMAN : Well, Greg Grandin, we want to thank you for being with us, Yale University history professor, Pulitzer Prize-winning author. His latest book, America, América: A New History of the New World . And we’ll link to your piece in The New York Times headlined “Trump’s Dated Strategy Is Putting Us on a Path to World War III .” We’ll link to you at democracynow.org.

Coming up, Chile has elected its most right-wing president since Augusto Pinochet. We’ll go to Santiago to speak with the renowned Chilean writer Ariel Dorfman. This is Democracy Now! We’ll also, later in the broadcast, look at the untold story of how Jeffrey Epstein got rich. Back in 30 seconds.

[break]

AMY GOODMAN : “Una Canción,” “A Song,” by the Cuban musician Silvio Rodríguez, performing at New York’s Central Park years ago.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Yep, Passkeys Still Have Problems

Lobsters
fy.blackhats.net.au
2025-12-17 13:10:05
Comments...
Original Article

It's now late into 2025, and just over a year since I wrote my last post on Passkeys. The prevailing dialogue that I see from thought leaders is "addressing common misconceptions" around Passkeys, the implication being that "you just don't understand it correctly" if you have doubts. Clearly I don't understand Passkeys in that case.

And yet, I am here to once again say - yep, it's 2025 and Passkeys still have all the issues I've mentioned before, and a few new ones I've learnt! Let's round up the year together then.

Too Lazy - Didn't Read

  • Passkeys have flaws - learn about them and use them on your terms . Don't write them off wholesale based on this blog. I, the author of this blog, use Passkeys!!!
  • DO engage with and learn about Credential Managers (aka Password Managers). This is where the Passkey is stored.
  • DO use a Credential Manager you control and can backup. I recommend Bitwarden or Vaultwarden which allow backups to be taken easily.
  • AVOID using a platform (Apple, Google) Credential Manager as your only Passkey repository - these can't easily backed up and you CAN be locked out permanently.
    • IF you use a platform Passkey manager, frequently sync it with FIDO Credential Exchange to an external Credential Manager you can backup/control.
    • OR use both the platform Passkey manager AND a Credential Manager you control in parallel.
  • For high value accounts such as email which are on the account recovery path
    • DO use Yubikeys for your email account as the Passkey store.
    • DO keep strong machine generated passwords + TOTP in your Credential Managers as alternatives to Passkeys for your email accounts.
  • DO a thought experiment - if I lost access to my Credential Manager what is the recovery path? Ensure you can rebuild from disaster.

So what has changed?

The major change in the last 12 months has been the introduction of the FIDO Credential Exchange Specification .

Most people within the tech community who have dismissed my claim that "Passkeys are a form of vendor lockin" are now pointing at this specification as proof that this claim is now wrong.

"See! Look! You can export your credentials to another Passkey provider if you want! We aren't locking you in!!!"

I have to agree - this is great if you want to change which walled-garden you live inside. However it doesn't assist with the day to day usage of Passkeys when you have devices from different vendor ecosystems. Nor does it make it easier for me to use a Passkey provider outside of my vendors platform provider.

Example: Let's say that I have an Windows Desktop and a Macbook Pro - I can sign up a Passkey on the Macbook Pro but I can't then use it on the Windows Desktop. FIDO Credential Exchange lets me copy from Apple's Keychain to whatever provider I use on the Windows machine. But now I have to do that exchange every time I enrol a new Passkey . Similar I would need to do the reverse from Windows to Mac every time that I sign up on the Windows machine.

So day to day, this changes very little - but if I want to go from "all in on Apple" to "all in on Google" then I can do a big-bang migration and jump from once garden to the next. But if you have mixed device ecosystems (like uhhh ... you know. Most of the world does) then very little will change for you with this.

But if I use my own Credential Manager (e.g. Vaultwarden) then I can happily work between multiple ecosystems.

What's the same?

Thought Leadership

Today I saw this excellent quote in the context of why Passkeys are better than Password+TOTP in a Password Manager:

Individuals having to learn to use password management software and be vigilant against phishing is an industry failure, not a personal success.

Even giving as much benefit of the doubt to this statement, and that the "and" might be load bearing we have to ask - Where are passkeys stored?

image

So we still have to teach individuals about password (credential) managers, and how Passkeys work so that people trust them. That fundamental truth hasn't changed.

But not only this - if a person is choosing a password+TOTP over a Passkey, we have to ask "why is that"? Do we think that it's truly about arrogance? Do we think that this user believes they are more important? Or is there and underlying usability issue at play? Why might we be recommending this to others? Do we really think that Passkeys come without a need of education?

Maybe I'm fundamentally missing the original point of this comment. Maybe I am completely misinterpretting it. But I still think we need to say if a person chooses password and TOTP over a Passkey even once they are informed of the choices, then Passkeys have failed that user. What could we have done better?

Perhaps one could interpret this statement as you don't need to teach users about Passkeys if they are using their ✨ m a g i c a l ✨ platform Passkey manager since it's so much nicer than a password and TOTP. And that leads to ...

It's Still Vendor Lockin

In economics, vendor lock-in, [...] makes a customer dependent on a vendor for products, unable to use another vendor without substantial switching costs.

citation - wikipedia

See, the big issue that the thought leaders seem to get wrong is that they believe that if you can use FIDO Credential Exchange, then you aren't locked in because you can move between Passkey providers.

But if we aren't teaching our users about credential management, didn't we just silently lock them into to our platform Passkey manager?

Not only that, when you try to go against the platform manager, it's the continual friction at each stage of the users experience. It makes the cost to switch high because at each point you encounter friction if you deviate from the vendors intended paths.

For example, consider the Apple Passkey modal:

image

MacOS 15.7.1 taken on 2025-10-29

The majority of this modal is dedicated to "you should make a Passkey in your Apple Keychain". If you want to use your Android phone or a Security Key, where would I click? Oh yes, Other Options .

Per Apple's Human Interface Guidelines :

Make buttons easy for people to use. It’s essential to include enough space around a button so that people can visually distinguish it from surrounding components and content. Giving a button enough space is also critical for helping people select or activate it, regardless of the method of input they use.

image

MacOS 15.7.1 taken on 2025-10-29

When you select Other Options this is what you see - see how Touch ID is still the default, despite the fact that I already indicated I don't want to use it by selecting Other Options ? At this point I would need to select Security Key and then click again to use my key. Similar for Android Phone.

And guess what - my preferences and choices are never remembered. I guess it's true what they say.

Software engineers don't understand consent, and it shows.

Google Chrome has a similar set of Modals and nudges (though props to Chrome, they at least implicitly activate your security key from the first modal so a power user who knows the trick can use it). So they are just as bad here IMO.

This is what I mean by "vendor lockin". It's not just about where the private keys are stored. It's the continual friction at each step of the interaction when you deviate from the vendors intended path. It's about making it so annoying to use anything else that you settle into one vendors ecosystem. It's about the lack of communication about where Passkeys are stored that tricks users into settling into their vendor ecosystem. That's vendor lock-in.

Cloud Keychains Are Still Blowing Up Data

We still get reports of people losing Passkeys from Apple Keychain. We similarly get reports of Android phones that one day just stop creating new Passkeys, or stop being able to use existing ones. One exceptional story we saw recently was of an Android device that stopped using it's onboard Passkeys and also stopped accepting NFC key. USB CTAP would still function, and all the historical fixes we've seen (such as full device resets) would not work. So now what? I'm not sure of the outcome of this story, but my assumption is there was not a happy ending.

If someone ends up locked out of their accounts because their Passkeys got nuked silently, what are we meant to do to help them?

Vendors Can Lock You Out

Dr Paris Buttfield-Addison was locked out of their Apple account .

I recommend you read the post, but the side effect - every Passkey they had in an Apple keychain is now unrecoverable.

There is just as much evidence about the same practices with Google / Android.

I honestly don't think I have to say much else, this is terrifying that every account you own could be destroyed by a single action where you have no recourse.

Authentication Providers Still Miscommunicate

We still have issues where services that are embracing Passkeys are communicating badly about them. The gold standard of miscommunication came to me a few months ago infact (2025-10-29) when a company emailed me this statement:

Passkeys use your unique features – known as biometrics – like your facial features, your fingerprint or a PIN to let us know that it’s really you. They provide increased security because unlike a password or username, they can’t be shared with anyone, making them phishing resistant.

As someone who is deeply aware of how webauthn works I know that my facial features or fingerprint never really leave my device. However asking my partner (context: my partner is a veternary surgeon, and so I feel justified in claiming that she is a very intelligent and educated woman) to read this, her interpretation was:

So this means a Passkey sends my face or fingerprint over the internet for the service to verify? Is that also why they believe it is phishing resistant because you can't clone my face or my fingerprint?

This is a smart, educated person, with the title of doctor , and even she is concluding that Passkeys are sending biometrics over the internet. What are people in other disciplines going to think? What about people with a cognitive impairment or who not have access to education about Passkeys?

This kind of messaging that leads people to believe we are sending personal physical features over the internet is harmful because most people will not want to send these data to a remote service . This completely undermines the trust in Passkeys because we are establishing to people that they are personally invasive in a way that username and passwords are not!

And guess what - platform Passkey provider modals/dialogs don't do anything to counter this information and often leave users with the same feeling.

Authentication Providers Are Still Playing Silly Games With User Choice

A past complaint was that I had encountered services that only accepted a single Passkey as they assumed you would use a synchronised cloud keychain of some kind. In 2025 I still see a handful of these services, but mostly the large problem sites have now finally allowed you to enrol multiple Passkeys.

But that doesn't stop sites pulling tricks on you.

I've encountered multiple sites that now use authenticatorAttachment options to force you to use a platform bound Passkey. In other words, they force you into Google or Apple. No password manager, no security key, no choices.

I won't claim this one as an attempt at "vendor lockin" by the big players, but it is a reflection of what developers believe a Passkey to be - they believe it means a private key stored in one of those vendors devices, and nothing else. So much of this comes from the confused historical origins of Passkeys and we aren't doing anything to change it.

When I have confronted these sites about the mispractice, they pretty much shrugged and said "well no one else has complained so meh". Guess I won't be enrolling a Passkey with you then.

One other site that pulled this said "instead of selecting continue, select this other option and you get the authenticatorAttachment=cross-platform setting. Except that they could literally do nothing with authenticatorAttachment and leave it up to the platform modals allowing me the choice (and fewer friction burns) of choosing where I want to enrol my Passkey.

Another very naughty website attempts to enroll a Passkey on your device with no prior warning or consent when you login, which is very surprising to anyone and seems very deceptive as a practice. Ironically same vendor doesn't use your passkey when you go to sign in again anyway.

Conclusion

Yep, Passkeys Still Have Problems.

But it's not all doom and gloom.

Most of the issues are around platform Passkey providers like Apple or Google.

The best thing you can do as a user, and for anyone in your life you want to help, is to be educated about Credential Managers. Regardless of Passwords, TOTP, Passkeys or anything else, empowering people to manage and think about their online security via a Credential Manager they feel they control and understand is critical - not an "industry failure".

Using a Credential Manager that you have control over shields you from the account lockout and platform blow-up risks that exist with platform Passkeys. Additionally most Credential Managers will allow you to backup your credentials too. It can be a great idea to do this every few months and put the content onto a USB drive in a safe location.

If you do choose to use a platform Passkey provider, you can "emulate" this backup ability by using the credential export function to another Passkey provider, and then do the backups from there.

You can also use a Yubikey as a Credential Manager if you want - modern keys (firmware version 5.7 and greater) can store up to 150 Passkeys on them, so you could consider skipping software Credential Managers entirely for some accounts.

The most critical accounts you own though need some special care. Email is one of those - email generally is the path by which all other credential resets and account recovery flows occur. This means losing your email access is the most devastating loss as anything else could potentially be recovered.

For email, this is why I recommend using hardware security keys (yubikeys are the gold standard here) if you want Passkeys to protect your email. Always keep a strong password and TOTP as an extra recovery path, but don't use it day to day since it can be phished. Ensure these details are physically secure and backed up - again a USB drive or even a print out on paper in a safe and secure location so that you can "bootstrap your accounts" in the case of a major failure.

If you are an Apple or Google employee - change your dialogs to allow remembering choices the user has previously made on sites, or wholesale allow skipping some parts - for example I want to skip straight to Security Key, and maybe I'll choose to go back for something else. But let me make that choice. Similar, make the choice to use different Passkey providers a first-class citizen in the UI, not just a tiny text afterthought.

If you are a developer deploying Passkeys, then don't use any of the pre-filtering Webauthn options or javascript API's. Just leave it to the users platform modals to let the person choose. If you want people to enroll a passkey on sign in, communicate that before you attempt the enrolment. Remember kids, consent is paramount.

But of course - maybe I just "don't understand Passkeys correctly". I am but an underachiving white man on the internet after all.

EDIT: 2025-12-17 - expanded on the password/totp + password manager argument.

How to use the holidays to stop our ‘WhatsApp aunties’ falling for AI

Guardian
www.theguardian.com
2025-12-17 13:02:59
Family members can be sweet and relentless but how can we aid our relatives in the age of new tech and device addiction • Don’t get The Long Wave delivered to your inbox? Sign up here I don’t want to sound dramatic but, a few weeks ago, something happened that has completely changed how I view onli...
Original Article

I don’t want to sound dramatic but, a few weeks ago, something happened that has completely changed how I view online material. I fell for AI-generated content. For someone who is constantly squabbling with older relatives about how little they question what they see online, this was a profoundly unsettling and humbling experience. And it made me think about how, during this holiday period, we could all use this as an opportunity to approach those conversations with the “WhatsApp aunties” more sensitively.

From ‘WhatsApp Aunties’ to ‘AI Aunties’

I think I have the perfect sample of WhatsApp aunties. Sadly displaced from Sudan due to war, a permanently online group of women, some direct aunts, some not, but all aunties nonetheless, sit in a control room of sorts in their different cities and send out daily broadcasts that simulate as much as possible the interactions and updates they would have shared had they still been living in the same place. They even have office hours. One can divine the start of the day in their respective locations as they clock in and the forwards begin: First, it is morning greetings, maybe an embellished picture of Quranic verses or a graphic of flowers, wishing you a good day.

Then, the hardcore stuff. Snippets of videos from war zones back home, clipped debates between political antagonists, and sometimes entire YouTube episodes of interviews. After this news shift comes the lighter one (secretly my favourite): TikTok and Instagram reels of Arab celebrities with too much plastic surgery accompanied by scream emojis, footage from family and friend weddings across the world, captioned with love heart eyes. The stream is interspersed with the longest voice memos you will ever receive, asking how you are and telling you how they are with an introductory and concluding prayer session. It is sweet and relentless.


AI Aunties

All of this is dumped with an abandon that suggests no understanding of or respect for phone memory limitations. Whenever my mother casually mentions that her phone is acting up and mutters something about no space, my heart sinks. I know that hours and hours of deletions of grainy videos are upon me. But most galling is how much fake content it includes. The WhatsApp aunties have become AI aunties. This was frankly a problem even before AI became so sophisticated, but it is now much, much worse. There is the harmless stuff; cats hugging babies or penguins feeding themselves with cutlery. I try not to get too agitated by this or point out that it’s fake. But when it’s videos of Taylor Swift endorsing the pro-Palestine movement, it’s impossible to let it slide.

AI baby penguin eating, Ai fashion model, and cat with baby.
The harmless stuff … AI baby penguin eating, Ai fashion model, and cat with baby. Illustration: Guardian Pictures/Getty Images

The result is a series of exchanges that are both saddening and enraging. Aunties will either take it personally, like I am disrespecting them by implying they can’t tell what’s real or not, and double down. Or they will express genuinely innocent beliefs in the veracity of online content, imbuing the internet with the same standards of TV or radio they grew up with.

Telling the aunties that something is entirely fake is like asking them to imagine a TV news broadcast is not real. Also, they are actually receiving news broadcast clips on their phones that are not real. You end up sounding like the crazy one, trying to explain that a living, breathing, walking, talking person is just pixels generated from prompts.


To argue or not to argue

In a recent episode of Subway Takes, comedian Ola Labib said we shouldn’t try to convince elders that AI content isn’t real. Her argument: Let them have their little comforts. I kind of get that, what harm is it doing really? But there is an emotional element to it as well. Policing elders’ content feels to me like a manifestation of a deep-seated fear that they’re losing it, that their faculties are waning, as they succumb to old age and the bewildering assaults of new tech and device addiction. I think it is truly distressing for people to see parents and relatives increasingly become addicted to their phones and become slightly addled, a window into a sort of premature senility.

But there are social and political reasons too, for pushing back. Aunties (and, to a lesser degree, uncles) have a huge amount of disseminative power and a lot of free time. They wield a formidable authority, particularly in diaspora communities, both as enforcers of values, as organisers and sponsors of social events, and generally as gatekeepers of community interactions and upholders of norms. Collectively and individually, they are forces to be reckoned with, which makes disagreements even more challenging and fraught with risks of falling foul of powerful elders. But they are force multipliers in terms of spreading fake content that is politically inflammatory or conspiratorial, and when unchallenged, they contribute to the general degradation of the information ecosystem and its associated political fallout.


How to help them

So, I would say talk to them, keep talking to them, but do it kindly, with time and explanation, rather than frustration and bewilderment. Maybe just acknowledge the content first before pointing out its fakery – a “really cool!” followed a little while later with a “actually, do you think that’s real? I’m not sure”. Also, furnish them with the “tells”: video glitches, lack of shadows, weird blinking. Bear in mind what the world looks like to them. It is a place that is changing too rapidly to assimilate how it is happening. Our elders are also, simply, getting older. With that comes all sorts of uncertainties and unsettlement; loneliness, loss of identity as work is retired from, and children age out of parenting. Exacerbating that are the vast distances that now often separate elders from their kin and peers. Online content and its constant exchange are about so much more than sharing information; it is a new language, almost phatic, for trying to connect.

Remember that the tech is evolving so quickly that even the most savvy have to be vigilant. I now have to be on alert after admiring a song with album cover art, a music video, a richly talented singer and fantastic accompanying chorus. After days of trying to hunt down the artist, I was thunderstruck to find out it was all AI. It will happen to all of us. Welcome me to the aunties brigade. Please be kind. Break it to me gently.

Headlines for December 17, 2025

Democracy Now!
www.democracynow.org
2025-12-17 13:00:00
Trump Orders Blockade on Sanctioned Oil Tankers Entering and Leaving Venezuela, ICC Rejects Israel’s Bid to Block War Crimes Probe in Gaza, First Funerals Held Today for Victims of Bondi Beach Massacre, Manhunt Still Underway for Brown University Shooting Suspect, MIT Professor Fatally Shot in...
Original Article

Headlines December 17, 2025

Watch Headlines

Trump Orders Blockade on Sanctioned Oil Tankers Entering and Leaving Venezuela

Dec 17, 2025

President Trump ordered a blockade on sanctioned oil tankers going to and from Venezuela Tuesday, ramping up his threats on the country’s leader, Nicolás Maduro. In a post on social media, Trump said, “Venezuela is completely surrounded by the largest Armada ever assembled in the History of South America. It will only get bigger, and the shock to them will be like nothing they have ever seen before.” Last week, the U.S. seized a tanker in the Caribbean Sea that was carrying Venezuelan oil for Cuba and China. Since September, the U.S. military has been carrying out airstrikes on alleged drug boats in the Caribbean and eastern Pacific near Venezuela, killing at least 95 people in 25 attacks. Meanwhile, Defense Secretary Pete Hegseth said Tuesday there are no plans to release the full unedited video showing a deadly second strike on an alleged drug boat on September 2. Legal experts and human rights groups have described the strike on two survivors clinging to the wreckage of the boat as a war crime. This comes as Trump’s Chief of Staff Susie Wiles suggested in an interview with Vanity Fair that the U.S. military’s attacks on alleged drug boats aim to ultimately topple President Maduro. Wiles said, “[Trump] wants to keep on blowing boats up until Maduro cries uncle. And people way smarter than me on that say that he will.” This is President Maduro speaking yesterday in Caracas.

President Nicolás Maduro : “We tell the people of the United States our truth, and it is very clear: Imperialism and the Nazi-fascist right wing want to colonize Venezuela to take our wealth — oil, gas, gold, iron, aluminum and other minerals. We have sworn to defend our homeland. And in Venezuela, peace will always prevail, along with stability and shared happiness for our people.”

We’ll have more on this story later in the broadcast.

ICC Rejects Israel’s Bid to Block War Crimes Probe in Gaza

Dec 17, 2025

In Gaza, Al Jazeera reports a 2-week-old infant has frozen to death, as winter storms batter the territory and Israel continues to block the entry of shelter and other humanitarian supplies for the hundreds of thousands of displaced Palestinians forced to live in makeshift tents or buildings damaged by Israeli bombings. Meanwhile, in another violation of the U.S.-brokered truce, Al Jazeera reports Israeli forces killed at least one Palestinian in the last 24 hours. This comes as efforts to recover the remains of the last Israeli hostage in Gaza have been hampered by the heavy rains.

The International Criminal Court has rejected Israel’s bid to block an investigation into war crimes committed by Israel in Gaza.

In more related news, Axios reports the White House sent an angry private message to Israeli Prime Minister Benjamin Netanyahu following the killing of Hamas senior commander Raed Saad, which Trump officials said violated the U.S.-brokered ceasefire that went into effect in October. Netanyahu is scheduled to meet Trump at Mar-a-Lago at the end of the month as tensions rise around the implementation of the next phase of the agreement with Hamas.

First Funerals Held Today for Victims of Bondi Beach Massacre

Dec 17, 2025

In Sydney, Australia, the first funerals were held today for victims of the Bondi Beach mass shooting, including for Rabbi Eli Schlanger and Rabbi Yaakov Levitan. Meanwhile, authorities announced that one of the gunmen, 24-year-old Naveed Akram, has been charged with 59 offenses, including murder and terrorism. The other gunman, his father, Sajid Akram, was shot dead by police at the scene.

Manhunt Still Underway for Brown University Shooting Suspect

Dec 17, 2025

In Rhode Island, the manhunt for the gunman who killed two students and injured nine others at Brown University on Saturday has entered its fifth day. Authorities released a new photo, “enhanced” videos and a video timeline showing a person of interest’s movements in the hours leading up to Saturday’s shooting. One shooting victim remains in critical condition, and two have been discharged from the hospital; six others are in stable condition. All classes and exams have been canceled, and the campus remains on edge. This is Parth Gupta, a senior at Brown.

Parth Gupta : “Brown was, honestly, one of the happiest Ivies. That’s how it was always known. But now, after everything that’s happened, it’s kind of become extremely scary. As a senior, having seen three years at Brown, like, I don’t even know how this incident is going to change campus. It’s very scary to go back, and it’s extremely unfortunate to see what happened to a place like Brown.”

MIT Professor Fatally Shot in His Home

Dec 17, 2025

An MIT professor was fatally shot at his home in Brookline, Massachusetts. Authorities have opened a homicide investigation into the killing of 47-year-old Nuno Loureiro, who was the director of MIT’s Plasma Science and Fusion Center. In January, President Biden had awarded the Presidential Early Career Award for Scientists and Engineers to Loureiro.

Trump’s Chief of Staff Wiles Says He Has an “Alcoholic’s Personality” in Explosive Vanity Fair Interview

Dec 17, 2025

Image Credit: Reuters/ Brian Snyder

In an explosive set of articles in Vanity Fair, journalist Christopher Whipple, author of a book on chiefs of staff, conducted 11 interviews with President Trump’s Chief of Staff Susie Wiles over the course of a year. Wiles characterized President Trump as having an “alcoholic’s personality” and said that she urged him not to pardon the most violent rioters from the January 6 insurrection. In the interview, she said that she thought Trump’s efforts to go after his political enemies would end after 90 days, and mentioned that his campaign against New York Attorney General Letitia James “may look like retribution.” Wiles also said that Vice President JD Vance has “been a conspiracy theorist for a decade,” and called Russell Vought, the budget director, “a right-wing absolute zealot.” She also called Elon Musk “an avowed ketamine” user and blasted his dismantling of USAID , saying, “No rational person could think the USAID process was a good one. Nobody.” On immigration, Wiles said, “I will concede that we’ve got to look harder at our process for deportation.” Wiles also criticized Attorney General Pam Bondi’s handling of the Epstein files, saying, “She said that the witness list, or the client list, was on her desk. There is no client list, and it sure as hell wasn’t on her desk.” Meanwhile, the deadline for the Justice Department to release the Epstein files is set for Friday, December 19.

Speaker Johnson Says He Will Not Call for a Vote to Extend Healthcare Subsidies

Dec 17, 2025

House Speaker Mike Johnson says he will not call for a vote to extend Affordable Care Act healthcare subsidies that are set to expire at the end of the year. As a result, millions of U.S. residents will have to pay higher health insurance premiums starting January. Republican Congressmember Mike Lawler of New York said, “Everybody has a responsibility to serve their district, to their constituents. You know what is funny? Three-quarters of people on Obamacare are in states Donald Trump won.” Some House Republicans have signaled that they would join Democrats in passing a discharge petition to force a House vote on a clean three-year extension of the subsidies, but that is unlikely to get a floor vote until next year.

Trump Expands Travel Ban to 20 More Countries

Dec 17, 2025

President Trump has signed an order expanding his travel ban into the U.S., with partial or full restrictions to nationals from at least 20 additional countries, including Burkina Faso, Mali, Niger, South Sudan and Syria. The Trump administration has also fully restricted travel into the U.S. for individuals holding Palestinian Authority travel documents.

NYT : Trump Admin Transfers 22 Cuban Immigrants to Guantánamo

Dec 17, 2025

The New York Times reports the Trump administration has transferred 22 Cuban immigrants to the Guantánamo Bay U.S. naval base in Cuba. The men are believed to be the first Cuban citizens to be sent to Guantánamo since Trump returned to office and began his mass deportation campaign. It is estimated that ICE has detained over 700 immigrants at Guantánamo this year.

Drone Attacks Killed Over 100 Civilians in Sudan This Month

Dec 17, 2025

In news from Sudan, the UAE -backed paramilitary Rapid Support Forces has been attempting to cover up its mass killings of civilians in the city of El Fasher by burning and burying bodies. That’s according to a new report by Yale’s Humanitarian Research Lab, which analyzed satellite images depicting RSF fighters likely disposing of tens of thousands of remains following its capture of El Fasher, the capital of North Darfur, in October. At least 1,500 people were killed in just 48 hours after the RSF seized the city. The report said, “This pattern of body disposal and destruction is ongoing.”

This comes as over 100 civilians were killed in drone attacks on the Kordofan region, where fighting between the RSF and Sudanese military has intensified. Tens of thousands of people have been displaced as warring parties shift focus toward Kordofan. U.N. experts have described Sudan’s war as the world’s largest humanitarian disaster.

M23 Rebel Group Announces Exit from Key Town in the Democratic Republic of the Congo

Dec 17, 2025

In the Democratic Republic of the Congo, M23 leaders say they have agreed to withdraw from the key town of Uvira in the eastern DRC at the request of the Trump administration. This came just days after Secretary of State Marco Rubio condemned the city’s capture last week, saying it violated a U.S.-brokered truce signed by Rwandan President Paul Kagame and DRC leader Félix Tshisekedi earlier this month at a ceremony in Washington, D.C., hosted by Trump. M23 fighters are not signatories of that deal and have been involved in parallel peace talks led by Qatar. Rwanda has been repeatedly accused of backing M23.

In related news, Human Rights Watch reports at least 22 civilians were killed and scores more injured in an attack by militia fighters in late November 2025 on a territory in the western DRC . As ethnic conflicts rise in the region, HRW said in a statement, “The global focus on the peace accords in eastern Congo shouldn’t distract from the unchecked violence and injustice and the cycles of impunity in other areas.”

Toxic Air Pollution Forces Schools in India to Cancel In-Person Classes and Employees to Work from Home

Dec 17, 2025

In India, authorities are mandating all private and government employers to direct staff to work from home, and schools have canceled in-person classes, as dense toxic smog has engulfed New Delhi, pushing dangerous pollution levels to a record high. Healthcare officials have advised residents to avoid all outdoor activities and to wear a mask, as hospitals have reported a rising number of people suffering from breathing conditions and eye irritation. The toxic haze has also affected visibility, impacting travel, with dozens of flights and trains delayed. This is a tourist who was stranded in New Delhi.

Aryan Punia : “Visibility is very low. I can’t see anything. We reached here by car yesterday. Due to fog and pollution, we could not see anything. We came to India Gate, but we can’t see it. We can hardly see it as we have come closer. Pollution is also affecting my health a lot.”

Greeks Protest Against Low Wages as Parliament Approves New Budget

Dec 17, 2025

Greece’s Parliament approved a new budget on Tuesday as massive protests were held by farmers and public-sector workers denouncing low wages amid skyrocketing food and housing costs. Earlier on Tuesday, protesters gathered in Athens.

Argyria Rotokritou : “We are striking today across the entire public sector and coordinating with the struggle waged by farmers against the government’s passage of this budget. It is a budget that cuts millions from public hospitals, where I also work, and channels the money into military spending. It hands it to the banks. We will not allow this.”

Warner Bros Rejects Paramount’s $108 Billion Hostile Takeover Bid

Dec 17, 2025

Warner Bros. Discovery is reportedly rejecting Paramount Skydance’s $108 billion hostile takeover bid to acquire the company. On Tuesday, Affinity Partners, which is run by President Trump’s son-in-law Jared Kushner, backed out of Paramount’s deal. The move paves the way for Netflix to go ahead with its $83 billion bid for Warner Bros.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Coursera to combine with Udemy

Hacker News
investor.coursera.com
2025-12-17 12:45:40
Comments...

Microsoft asks IT admins to reach out for Windows IIS failures fix

Bleeping Computer
www.bleepingcomputer.com
2025-12-17 12:30:32
Microsoft has asked businesses to reach out for advice on how to temporarily mitigate a Message Queuing (MSMQ) issue causing enterprise apps and Internet Information Services (IIS) sites to fail. [...]...
Original Article

Windows

Microsoft has asked businesses to reach out for advice on how to temporarily mitigate a known Message Queuing (MSMQ) issue causing enterprise apps and Internet Information Services (IIS) sites to fail.

MSMQ is an optional Windows service commonly used in enterprise environments that helps apps communicate over a network.

The known issue mainly affects enterprise users with Windows 10 22H2, Windows Server 2019, and Windows Server 2016 devices that have installed the KB5071546 , KB5071544 , and KB5071543 security updates released during the December 2025 Patch Tuesday.

Wiz

While Microsoft is investigating it and working on a fix, in a Tuesday update to the Windows release health dashboard, it advised enterprise customers to reach out for details on how to temporarily mitigate this bug in their environments.

"Individuals using Windows Home or Pro editions on personal devices are very unlikely to experience this issue. This issue primarily affects enterprise or managed IT environments," Microsoft said . "A workaround is available for affected devices. To apply the workaround and mitigate this issue in your organization, please contact Microsoft Support for business ."

As Microsoft explained when it acknowledged the issue on Monday, affected users are experiencing a wide range of symptoms, from inactive MSMQ queues and applications unable to write to queues to IIS sites failing with "insufficient resources" errors. Some impacted systems are also displaying misleading "There is insufficient disk space or memory" messages, even though sufficient resources are available.

The problem stems from changes to the MSMQ security model that have modified permissions on a critical system folder, requiring MSMQ users to have write access to a directory that is usually restricted to administrators.

"This issue is caused by the recent changes introduced to the MSMQ security model and NTFS permissions on C:\Windows\System32\MSMQ\storage folder. MSMQ users now require write access to this folder, which is normally restricted to administrators," Microsoft explained . "As a result, attempts to send messages via MSMQ APIs might fail with resource errors. This issue also impacts clustered MSMQ environments under load."

Microsoft has yet to provide a timeline for when a fix will be available and has not confirmed whether it will issue an emergency update or wait for the next scheduled release. For now, IT admins dealing with this issue should reach out to Microsoft's business support team for a temporary workaround or may need to consider rolling back the updates.

In July, Microsoft also asked businesses to reach out for advice on how to work around another known issue causing Cluster service and VM restart problems after installing the July 2025 Windows Server 2019 security updates.

tines

Break down IAM silos like Bitpanda, KnowBe4, and PathAI

Broken IAM isn't just an IT problem - the impact ripples across your whole business.

This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

Amazon in talks to invest $10bn in developer of ChatGPT

Guardian
www.theguardian.com
2025-12-17 12:17:05
OpenAI seeking to strike latest deal in its efforts to pay for huge spending on datacentresBusiness live – latest updatesAmazon is in talks to invest more than $10bn (£7.5bn) in OpenAI, in the latest funding deal being struck by the startup behind ChatGPT. If it goes ahead, the market valuation of O...
Original Article

Amazon is in talks to invest more than $10bn (£7.5bn) in OpenAI, in the latest funding deal being struck by the startup behind ChatGPT .

If it goes ahead, the market valuation of OpenAI could rise above $500bn, according to The Information, a tech news site that revealed the negotiations .

Amazon, which is best known as an online retailer, is also the world’s largest datacentre provider and its investment would help OpenAI pay for its commitments to rent capacity from cloud computing companies – including Amazon .

OpenAI said last month it would spend $38bn on capacity from Amazon Web Services – the company’s datacentre arm – over seven years. The Information said that OpenAI planned to use Amazon’s Trainium chips, which compete with Nvidia and Google’s chips. It also reported that Amazon’s financing could lead to a broader fundraising round with other investors.

OpenAI’s spending commitment on compute – the chips and servers that power its chatbot – is $1.4tn over the next eight years, a figure far in excess of its reported $13bn in annual revenues.

As a result, the lossmaking company has been seeking further funding and has converted its main business into a for-profit corporation. Its main longtime backer, Microsoft, has taken a stake of roughly 27% in a deal that valued OpenAI at $500bn .

OpenAI is also considering an initial public offering – selling its shares to the general public – in a move that could value the company at up to $1tn, according to Reuters.

Other deals struck by OpenAI this year include Oracle spending $300bn on building datacentres in Texas, New Mexico, Michigan and Wisconsin. OpenAI is expected to pay back roughly the same amount to use the sites.

In another transaction with Nvidia , OpenAI will pay in cash for chips and Nvidia will invest in OpenAI for non-controlling shares.

OpenAI announced on Tuesday that it had hired the former UK chancellor George Osborne to develop relationships with governments around the world and broker national-level AI projects.

Sam Altman, OpenAI’s chief executive, has declared a “code red” staff alert to lead a fightback against competitors led by Google, whose update of its Gemini AI tool gave it an edge over rivals including ChatGPT.

The Amazon talks reportedly include discussing commercial opportunities and selling a corporate version of ChatGPT to the online retailer.

OpenAI declined to comment. Amazon has been approached for comment.

How Twitter is (probably) crawling the Internet for AI

Lobsters
kitsunemimi.pw
2025-12-17 12:15:24
Comments...
Original Article

As a bored sysadmin you might SSH into one of your servers and run htop or tail -f access.log . Last Sunday was one of those tail -f access.log days.

You take a cursory look at your web server logs slowly scrolling past and see a bunch of requests come in. They look a bit odd.

142.147.166.136 - - [XX/Dec/2025:XX:XX:XX +0000] "GET /some/path2 HTTP/1.1" 200 1953 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" "-"
104.37.31.15 - - [XX/Dec/2025:XX:XX:XX +0000] "GET /some/path3 HTTP/1.1" 200 2091 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" "-"
23.226.210.75 - - [XX/Dec/2025:XX:XX:XX +0000] "GET /some/path4 HTTP/1.1" 200 1786 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" "-"
170.23.18.148 - - [XX/Dec/2025:XX:XX:XX +0000] "GET /some/path6 HTTP/1.1" 200 2415 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Trailer/93.3.8652.5" "-"
8.160.39.134 - - [XX/Dec/2025:XX:XX:XX +0000] "GET /some/path1 HTTP/1.1" 200 83209 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36" "-"
85.254.140.83 - - [XX/Dec/2025:XX:XX:XX +0000] "GET /some/path5 HTTP/1.1" 200 3441 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" "-"

" A rare Linux user, cool. ", you think. But wait:

Why aren't they loading any of CSS or images on those pages?

No referrers at all?

And what the heck is " Trailer/93.3.8652.5 "?

Investigating bot traffic

Plugging the last thing into Google doesn't really return much useful, except for a single German blog post [ 1 ] about a single IP with clearly bot-like behavior cycling through multiple user-agents, which are very similar to ours.

Now "stealth" web bots are not a new phenomenon by any means. But given a good clue I decided to investigate a bit more.

Having established that "Trailer" is apparently not part of any normal user-agent header I grep my logs for \sTrailer/[0-9]+ . This matches more than 10000 requests over the last month. Huh .

Not a single CSS, JS or image request. No robots.txt. Just pure HTML.

Only exactly one request made over IPv6 (even though the website in question supports it). [ 2 ]

No referrers on any of them.

Conversely, the spectrum of pages visited is extremely wide. More than 80% of URLs were visited only exactly once with this user agent. Notably including some very old stuff that usually nobody looks at. The IP addresses paint a similar picture. 91% of IPs make just one request and never visit again.

For a more useful overview you should plug the IPs into your favorite IP-lookup tool and check which networks (AS) they belong to, which I did. The most common ones are as follows:

2517 "AS212238 Datacamp Limited"
2210 "AS9009 M247 Europe SRL"
2090 "AS3257 GTT Communications Inc."
 903 "AS210906 UAB \"Bite Lietuva\""
 882 "AS203020 HostRoyale Technologies Pvt Ltd"
 723 "AS62874 Web2Objects LLC"
 622 "AS7979 Servers.com, Inc."

If these do not strike you as ISPs you usually use at home, you'd be right. They're datacenters and carriers.

The bottom of the list however turned out to be much more interesting:

4 "AS202914 Adeo Datacenter ApS"
4 "AS63179 Twitter Inc."
1 "AS44244 Iran Cell Service and Communication Company"

Twitter? The Twitter.com (now X.com)?

surely they shouldn't be here.

Twitter???

I initially assumed this to be a false-positive and went back to unprocessed logs to discover that - no - Twitter had indeed visited with this peculiar user agent. Specificially, from 69.12.56.x, 69.12.57.x and 69.12.58.x.

I took a step back and searched the logs for all request from this IP network. The result looked as follows:

69.12.59.37 - - [06/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.3" "-"
69.12.56.29 - - [06/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.3" "-"
69.12.59.31 - - [06/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 OPR/117.0.0.0" "-"
69.12.59.19 - - [06/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" "-"
69.12.57.39 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.3" "-"
69.12.59.33 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.10 Safari/605.1.1" "-"
69.12.59.36 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.3" "-"
69.12.56.7 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" "-"
69.12.56.34 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.3" "-"
69.12.58.21 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" "-"
69.12.58.1 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Trailer/93.3.8652.5" "-"
69.12.56.17 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.10 Safari/605.1.1" "-"
69.12.58.47 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Trailer/93.3.8652.5" "-"
69.12.58.4 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" "-"
69.12.56.47 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.10 Safari/605.1.1" "-"
69.12.59.24 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" "-"
69.12.57.2 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Trailer/93.3.8652.5" "-"
69.12.57.24 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" "-"
69.12.59.25 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" "-"
69.12.56.44 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.10 Safari/605.1.1" "-"
69.12.56.11 - - [07/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0" "-"
69.12.56.36 - - [08/Nov/2025:XX:XX:XX +0000] "..." XXX X "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Trailer/93.3.8652.5" "-"

The exact same bot traffic pattern. Never seen again from this network, except on these three days.

The immediate question of " What are they doing this for? " is best answered by performing traceroute to one of the IPs (this was a coincidental finding).

                                                                         Loss%   Snt   Last   Avg  Best  Wrst StDev
 5.|-- ae1-0.0001.prrx.02.dus.de.net.telefonica.de (62.53.13.223)         0.0%     2    7.3   7.6   7.3   7.8   0.4
 6.|-- ae3-0-grtdusix1.net.telefonicaglobalsolutions.com (213.140.51.62)  0.0%     2    7.5   7.5   7.5   7.6   0.0
 7.|-- 94.142.107.133                                                     0.0%     2    9.0   8.5   8.1   9.0   0.7
 8.|-- ???                                                               100.0     2    0.0   0.0   0.0   0.0   0.0
 9.|-- X.AI-LLC.ear4.Atlanta2.Level3.net (4.14.249.150)                   0.0%     2  122.5 122.7 122.5 122.8   0.2
10.|-- ???                                                               100.0     2    0.0   0.0   0.0   0.0   0.0

While AS63179 or 69.12.56.0/21 are only generally attributable to Twitter Inc, their carrier (Level 3) [ 3 ] has helpfully indicated in the reverse DNS that the company they're routing this particular network for is X.AI LLC.

So let's collect the theory so far:

  • X.AI is doing web scraping presumably to train Grok

  • their bots pretend to be browsers (badly) and do not follow robots.txt

  • they're using some kind of proxy, VPN or similar network

  • on three days in November they slipped up and used their own IP space

Connecting the dots

Now what's so special about all those other IPs visiting us?

Staring at the list of networks isn't going to help so it's time for some better tools. I started querying Spur for these IPs and this painted a very clear picture:

" Wait, it's all Oxylabs? "

" Always has been "

Oxylabs is apparently one of the largest proxy network providers. Basically, you pay them money and they let you use one of their many IPs to visit websites. They even advertise their services for use with AI, or for web scraping.

I do not want to go into legal questions, but while there are innocent use cases such as product price monitoring, any proxy network will inevitably be used for scalping, spamming and fraud. No matter how well-intentioned, the operator of a proxy network can hardly prevent this.

(In my opinion web scraping doesn't go into the "innocent" category either, but it's not as unequivocally bad as the other examples.)

Going back to the main topic: I revisited the top list of networks and found around 100 IPs from Verizon and Comcast on there too. Looking these up on Spur also indicates Oxylabs. So it appears that X.AI uses some percentage of residential proxies too.

To verify my discovery I googled to see if anyone else had connected Twitter or Grok to Oxylabs yet:

"Was curious what ASNs XAI / Grok uses since it doesn't show in @Cloudflare AI dashboard. Asked it to visit my website URL (with a few random chars in the path to verify) and apparently XAI is using residential IP proxies from companies like ABCproxy, Oxylabs and others. | Plus it uses fake useragents for things like iPhones, Mac, etc. I guess that's one way to bypass any blocks against AI scrapers. Seems pretty unethical."

The single mention [ 4 ] I found (ironically on Twitter itself) was a tweet from August 2025 and provided a direct confirmation that Grok does web scraping with spoofed user agents through Oxylabs.

Conclusion

Before I end this article I want to note that you don't have to just trust me that Twitter was crawling from their own IPs in November. If you check AbuseIPDB you can find a bunch of reports for the relevant days [ 7 ] [ 8 ] .

Today, we discovered by accident that Twitter (X.AI) is very likely running a hidden web scraping operation to feed their LLM models and using a major proxy network to hide their tracks.

Now this isn't a major breakthrough or anything, and you can bet that they're not the only ones doing this. Aggressive stealth crawlers are a common complaint of webmasters [ 9 ] , and often attributed to LLMs. But it's nice to have circumstantial evidence on who is behind this particular bot traffic.


Log level 'error' should mean that something needs to be fixed

Lobsters
utcc.utoronto.ca
2025-12-17 12:06:54
Comments...
Original Article

You're probably reading this page because you've attempted to access some part of my blog (Wandering Thoughts) or CSpace , the wiki thing it's part of. Unfortunately whatever you're using to do so has a HTTP User-Agent header value that is too generic or otherwise excessively suspicious. Unfortunately, as of early 2025 there's a plague of high volume crawlers (apparently in part to gather data for LLM training) that behave like this. To reduce the load on Wandering Thoughts I'm experimenting with (attempting to) block all of them, and you've run into this.

All HTTP User-Agent headers should clearly identify what they are, and for non-browser user agents, they should identify not just the software involved but also who specifically is using that software. An extremely generic value such as " Go-http-client/1.1 " is not something that I consider acceptable any more.

Chris Siebenmann, 2025-02-17

Deliberate Internet Shutdowns

Schneier
www.schneier.com
2025-12-17 12:02:01
For two days in September, Afghanistan had no internet. No satellite failed; no cable was cut. This was a deliberate outage, mandated by the Taliban government. It followed a more localized shutdown two weeks prior, reportedly instituted “to prevent immoral activities.” No additional exp...
Original Article

For two days in September, Afghanistan had no internet . No satellite failed; no cable was cut. This was a deliberate outage, mandated by the Taliban government. It followed a more localized shutdown two weeks prior, reportedly instituted “to prevent immoral activities.” No additional explanation was given. The timing couldn’t have been worse: communities still reeling from a major earthquake lost emergency communications , flights were grounded , and banking was interrupted . Afghanistan’s blackout is part of a wider pattern. Just since the end of September, there were also major nationwide internet shutdowns in Tanzania and Cameroon , and significant regional shutdowns in Pakistan and Nigeria . In all cases but one , authorities offered no official justification or acknowledgment, leaving millions unable to access information, contact loved ones, or express themselves through moments of crisis, elections, and protests.

The frequency of deliberate internet shutdowns has skyrocketed since the first notable example in Egypt in 2011 . Together with our colleagues at the digital rights organisation Access Now and the #KeepItOn coalition, we’ve tracked 296 deliberate internet shutdowns in 54 countries in 2024 , and at least 244 more in 2025 so far.

This is more than an inconvenience. The internet has become an essential piece of infrastructure, affecting how we live, work, and get our information. It’s also a major enabler of human rights, and turning off the internet can worsen or conceal a spectrum of abuses . These shutdowns silence societies, and they’re getting more and more common.

Shutdowns can be local or national, partial or total. In total blackouts, like Afghanistan or Tanzania, nothing works. But shutdowns are often targeted more granularly. Cellphone internet could be blocked, but not broadband. Specific news sites, social media platforms, and messaging systems could be blocked, leaving overall network access unaffected—as when Brazil shut off X (formerly Twitter) in 2024. Sometimes bandwidth is just throttled , making everything slower and unreliable.

Sometimes, internet shutdowns are used in political or military operations. In recent years, Russia and Ukraine have shut off parts of each other’s internet, and Israel has repeatedly shut off Palestinians’ internet in Gaza. Shutdowns of this type happened 25 times in 2024 , affecting people in 13 countries.

Reasons for the shutdowns are as varied as the countries that perpetrate them. General information control is just one. Shutdowns often come in response to political unrest, as governments try to prevent people from organizing and getting information; Panama had a regional shutdown this summer in response to protests . Or during elections, as opposition parties utilize the internet to mobilize supporters and communicate strategy. Belarusian president Alyaksandr Lukashenko , who has ruled since 1994, reportedly disabled the internet during elections earlier this year, following a similar move in 2020 . But they can also be more banal. Access Now documented countries disabling parts of the internet during student exam periods at least 16 times in 2024, including Algeria, Iraq, Jordan, Kenya, and India.

Iran’s shutdowns in 2022 and June of this year are good examples of a highly sophisticated effort, with layers of shutdowns that end up forcing people off the global internet and onto Iran’s surveilled, censored national intranet. India, meanwhile, has been the world shutdown leader for many years, with 855 distinct incidents. Myanmar is second with 149, followed by Pakistan and then Iran. All of this information is available on Access Now’s digital dashboard , where you can see breakdowns by region, country, type, geographic extent, and time.

There was a slight decline in shutdowns during the early years of the pandemic, but they have increased sharply since then. The reasons are varied, but a lot can be attributed to the rise in protest movements related to economic hardship and corruption, and general democratic backsliding and instability. In many countries today, shutdowns are a knee-jerk response to any form of unrest or protest, no matter how small.

A country’s ability to shut down the internet depends a lot on its infrastructure. In the US, for example, shutdowns would be hard to enforce. As we saw when discussions about a potential TikTok ban ramped up two years ago, the complex and multifaceted nature of our internet makes it very difficult to achieve. However, as we’ve seen with total nationwide shutdowns around the world, the ripple effects in all aspects of life are immense. (Remember the effects of just a small outage— CrowdStrike in 2024 —which crippled 8.5 million computers and cancelled 2,200 flights in the US alone?)

The more centralized the internet infrastructure, the easier it is to implement a shutdown. If a country has just one cellphone provider, or only two fiber optic cables connecting the nation to the rest of the world, shutting them down is easy .

Shutdowns are not only more common, but they’ve also become more harmful. Unlike in years past, when the internet was a nice option to have, or perhaps when internet penetration rates were significantly lower across the Global South, today the internet is an essential piece of societal infrastructure for the majorit y of the world’s population.

Access Now has long maintained that denying people access to the internet is a human rights violation, and has collected harrowing stories from places like Tigray in Ethiopia, Uganda , Annobon in Equatorial Guinea, and Iran . The internet is an essential tool for a spectrum of rights, including freedom of expression and assembly. Shutdowns make documenting ongoing human rights abuses and atrocities more difficult or impossible. They are also impactful on people’s daily lives, business, healthcare, education, finances, security, and safety, depending on the context. Shutdowns in conflict zones are particularly damaging, as they impact the ability of humanitarian actors to deliver aid and make it harder for people to find safe evacuation routes and civilian corridors.

Defenses on the ground are slim. Depending on the country and the type of shutdown, there can be workarounds. Everything, from VPNs to mesh networks to Starlink terminals to foreign SIM cards near borders, has been used with varying degrees of success. The tech-savvy sometimes have other options. But for most everyone in society, no internet means no internet—and all the effects of that loss.

The international community plays an important role in shaping how internet shutdowns are understood and addressed. World bodies have recognized that reliable internet access is an essential service, and could put more pressure on governments to keep the internet on in conflict-affected areas. But while international condemnation has worked in some cases ( Mauritius and South Sudan are two recent examples), countries seem to be learning from each other, resulting in both more shutdowns and new countries perpetrating them.

There’s still time to reverse the trend, if that’s what we want to do. Ultimately, the question comes down to whether or not governments will enshrine both a right to access information and freedom of expression in law and in practice. Keeping the internet on is a norm, but the trajectory from a single internet shutdown in 2011 to 2,000 blackouts 15 years later demonstrates how embedded the practice has become. The implications of that shift are still unfolding, but they reach far beyond the moment the screen goes dark.

This essay was written with Zach Rosson, and originally appeared in Gizmodo .

Tags: ,

Posted on December 17, 2025 at 7:02 AM 0 Comments

Sidebar photo of Bruce Schneier by Joe MacInnis.

The Wrong Question About Type Systems

Lobsters
furkan3ayraktar.github.io
2025-12-17 12:01:44
Comments...
Original Article

After more than eight years of professional Clojure development, I still get asked the same question: "Don't you miss types?"

I recently swapped Clojure for Typescript and Go, due to a career move. But looking back at my Clojure years, I realize the question assumes a tradeoff I never experienced. It frames the choice as safety versus convenience, as if I was trading correctness for speed. The longer I think about it, the more I believe the question comes from false assumptions.

Let me explain.

Taking the arguments seriously

I have heard every argument for static types. Rather than dismissing them, I want to engage with the strongest versions.

"Types enforce contracts across large teams. When fifty engineers touch a codebase, the argument goes, types become documentation that the compiler enforces. No miscommunication, no runtime surprises at integration boundaries."

But in dynamic languages, you can also solve for documentation and correctness by adding schema validation at the boundaries. Tools like Malli or Spec can give you strong, checkable guarantees at the seams where parts meet. If your architecture consists of small, focused components with clear interfaces (like the Polylith architecture ), the boundaries are most of your surface area. The "interior" where unvalidated data flows is minimized.

"Types enable refactoring with confidence. Change a function signature, and the compiler shows you everything that breaks. In a dynamic language, you rely on tests and grep."

Modern Clojure tooling handles this well. Cursive, Calva, and clj-kondo all provide structural navigation and refactoring. More importantly, Clojure's culture encourages additive change over breaking change. Rich Hickey's Spec-ulation keynote makes the case that breaking changes are simply broken. You don't rename things and hope. You deprecate, you evolve, you maintain compatibility.

"Types encode complex invariants. When you want Money<USD> and Money<EUR> to be incompatible, types make invalid states unrepresentable."

Specs and Malli schemas can encode and validate invariants like this, with instrumentation that checks at runtime. That isn't the same as making misuse impossible by construction, but it can still be very effective in practice. The difference is compile-time versus runtime checking. But here is the thing: many mainstream typed languages are not as safe as advertised. TypeScript has any and type assertions. Go has interface{} and nil panics. Java has null everywhere and erased generics. They still prevent plenty of real bugs, but the guarantee surface is often smaller than people assume. The truly rigorous type systems like Haskell or Idris exist, but they're rarely what people mean when they argue for types.

"Types improve editor tooling and discoverability. Autocomplete, jump-to-definition, 'what can I call on this?' Types make all of this instant."

In Clojure, the answer is simpler: if it is a function, it is callable. The data is maps and vectors. You already know what operations exist. What you still need is a shared, checkable description of shapes and invariants, and that is where schemas and specs earn their keep. And the REPL gives you something better than autocomplete. You can try it and see what happens in milliseconds.

What is actually different

I will concede some ground. There are things types give you that Clojure handles differently.

Exhaustiveness checking is real. When you have a closed set of variants, the compiler can tell you when you forgot a case. In Clojure, a cond might silently return nil . You catch this with tests, but you have to write them.

Propagation is real. Types flow through your entire codebase automatically. With schemas, you annotate boundaries explicitly. Types are more pervasive. But pervasive can also mean noisy.

Compile-time guarantees are real. "Impossible to compile" is different from "fails when instrumented." For a two-hour batch job, finding out at minute ninety hurts.

But that last point deserves scrutiny. When you develop at the REPL, testing every small piece as you write it, connected to a running system, how often does something survive to minute ninety that types would have caught? The batch job failure is a symptom of a development process where feedback comes too late. Clojure's REPL-driven workflow means you have already exercised the code paths before you commit.

After taking apart the technical arguments, I arrived at what I think is the honest answer: types are also a social technology, not just a technical one.

They lower the bar for hiring. A larger talent pool can be productive faster. They help with onboarding. The codebase is "self-documenting." They simplify code review. Less context is needed to understand changes.

But even these claims dissolve under examination.

On self-documentation: I have seen typed codebases with data: any , payload: Map<String, Object> , and handleThing(x: SomeAbstractFactoryBean<T extends BaseEntity>) . This documents nothing. Bad types might be worse than no types. They give false confidence. Good types require discipline. But discipline is exactly what makes specs and tests useful. We are back to: types do not replace discipline, they move where it is applied.

On easier code review: In practice, dependency injection-heavy typed OOP codebases have a different problem. You click on a method and land on an interface. You click on the interface and find four implementations. Which one is actually called? You check the dependency injection configuration, maybe in a separate XML file or scattered across annotations. You finally find the code, and it is two hundred lines because mutability requires defensive ceremony.

In Clojure: it is a function. Click on it and you land on the code, not an interface. It is fifteen lines because data goes in and data comes out. And if you are still confused, you can run it in the REPL right now.

The indirection tax in typed OOP is massive and rarely acknowledged. (This is a critique of certain enterprise OOP/DI styles, not of typed FP languages like Haskell or OCaml.) "Less context needed" assumes the architecture is simple. But the architecture is rarely simple because the type system encourages abstraction layers.

On the deeper issue: Working on the Polylith architecture taught me something that reframes this entire debate. Most software complexity traces back to one thing: coordination . When you change something in one place and have to update something else to match, that is coordination. When two parts of a system need to agree on a shape or a contract, that is coordination. When teams need to synchronize their understanding, that is coordination.

Joakim Tengstrand, who created Polylith, wrote about this extensively in The Origin of Complexity . His insight is that almost every design principle that works, from "don't repeat yourself" to "use pure functions" to "make small commits," can be reframed as reducing coordination .

Types shift coordination. They can reduce coordination by making expectations explicit and mechanically checked. But when type information flows everywhere, every function signature becomes a contract that other parts must coordinate with. Change a type, and the ripple spreads. The more elaborate (and the more globally shared) the type model, the more coordination it can demand. Is an email address really "owned" by your User class? Is a phone number part of your Contact type? These things exist in the world independent of your object hierarchy. Types can push you into ownership decisions that may not reflect reality, and those decisions ripple through your codebase as coupling.

The biggest bugs I have seen were never type errors. They were misunderstandings about the domain. They were wrong assumptions about what the system should do. They were coordination failures between teams or between code and reality. Type systems do not catch these. You need testing anyway. And the coupling that types introduce makes the system harder to change when you discover you were wrong.

The reframe

Here is what I have come to believe: the question is not types versus no types. That framing misses everything important.

Clojure works not because it lacks types, but because it is a system of design decisions that reinforce each other. The dynamism is one piece. Remove any of the following pieces, and the whole would be weaker.

REPL-driven development. Not just "a REPL." Most languages have that. Clojure's REPL is connected to your running program. You are not testing in isolation. You are reaching into a live system and poking it. You do not imagine what will happen, you try it. The feedback loop is seconds. This only works because of dynamism. Redefining a function without restarting is trivial when there is no type to invalidate.

Functional programming with immutability by default. These eliminate entire categories of bugs that types exist to prevent. "What state is this object in?" does not apply when there is no mutable state. "Who changed this?" Nobody. Mutable state introduces coordination. Every piece of code that can mutate shared state needs to coordinate with every other piece. Immutability removes that entire category of coordination from your system. In many ecosystems, types are used as guardrails around mutation and aliasing. Without mutation, you need fewer guardrails. Composition becomes trivial.

Homoiconicity. Code is data. Macros actually work. Your tooling, your editor, your REPL, your tests can all manipulate code the same way they manipulate data. This is why Clojure tooling caught up despite a smaller community. You are not parsing a complex grammar. You are reading lists.

Data-oriented programming. You use maps, vectors, sets. Not custom classes. Every function you already know works on every piece of data. No "how do I get the name out of this Person object." It is just (:name person) . As Alan Perlis wrote in his famous Epigrams on Programming : "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures."

Persistent data structures. Immutability would be impractical if every change required copying everything. Structural sharing makes it fast. This implementation detail is what makes the functional style viable for real work.

The sequence abstraction. Vectors, lists, maps, sets, files, database results, lazy infinite streams. They all respond to map , filter , reduce . You learn these operations once. They work everywhere.

Explicit state when needed. Atoms, refs, agents. Each with clear semantics. State is not forbidden. It is controlled. The language acknowledges reality while making the boundaries visible.

Spec and Malli as libraries, not language features. Types are usually baked in. Love them or not, you live with them. Clojure made validation optional and data-driven. You describe your data with data. You can generate tests, documentation, and validation from the same spec. Homoiconicity paying dividends again. (Yes, there is Typed Clojure / core.typed . This post is about idiomatic Clojure practice in the dynamic tradition.)

JVM stability and ecosystem access. You get to be radical in language design while being conservative in deployment. No new runtime to trust. Production-proven garbage collection, profiling, monitoring. Pragmatism that lets the interesting parts flourish.

Core team design philosophy. Rich Hickey's Simple Made Easy talk articulates this best: simple is not the same as easy. Simplicity is about lack of interleaving, about things having one role. As Dijkstra said, "Simplicity is a prerequisite for reliability." The Clojure core team embodies this. The refusal to add features just because people ask. No broken backwards compatibility. Taste and restraint. Rare in language design.

What do you optimize for?

Types optimize for one thing: checking certain properties before running. Clojure optimizes for something else: understanding and changing code quickly.

In other words: static types trade local friction for global guarantees; Clojure trades some global guarantees for interactive exploration, simpler composition, and lower incidental complexity.

These are different goals. Neither is wrong. But you cannot fully have both.

If you have a disciplined team that writes schemas and tests and keeps feedback loops short, I cannot name many domains where static types are a decisive technical advantage. There might be domains where types are convenient : compilers, language tooling, heavily generic library code. But "convenient" is weaker than the usual claims.

The tradeoff is not safety versus danger. It is discipline versus enforcement. External enforcement has costs: ceremony, indirection, slower feedback loops, and coordination overhead that compounds over time. Discipline has costs too: you have to actually maintain it.

After eight years, I know which trade I prefer. Solve problems, not puzzles, as Rich Hickey says. The question was never really about types.


Further reading

Simogo Legacy Collection review – remember when phone games were this wonderful?

Guardian
www.theguardian.com
2025-12-17 11:52:58
PC, Nintendo Switch/Switch 2; SimogoA suite of iOS classics is lovingly preserved in this collection from the Swedish developer, early standard-setters of the meaningful smartphone game Fifteen years ago in Malmö, Sweden, animator Simon Flesser and programmer Magnus “Gordon” Gardebäck left their job...
Original Article

F ifteen years ago in Malmö, Sweden, animator Simon Flesser and programmer Magnus “Gordon” Gardebäck left their jobs at the now-defunct games studio Southend Interactive to strike out on their own. Tired of the fussy nature of console development, the pair would stake their claim on Apple’s App Store, which in 2010 was regarded as one of the most exciting frontiers in games. Mashing their names together to form a portmanteau, Flesser and Gardebäck became Simogo, and a consistently wonderful and forward-thinking games studios was born.

Simogo Legacy Collection represents the Swedish indie studio’s first seven games, released across its first five years. Originally released for iPhone and iPad from 2010 to 2015, Apple’s constantly changing standards meant that Simogo, like all iOS developers, had to either regularly update their games to comply with the latest specifications, or see their games rendered unplayable. The only solutions are either to perpetually issue updates, or find a way to bring the mobile game experience to other platforms.

Thank goodness Simogo decided on the latter. Like all of the studio’s work, this anthology of games is smartly designed, its contents arranged on a homescreen made to look like a smartphone’s – except, you know, full of wonderful little games and not horrid social media apps. Care has been taken to make sure you can play the games no matter your setup – on a screen with a controller, at a PC with mouse and keyboard, in portrait or landscape orientations. (My preference was to play on a Switch, with the Joy-Cons removed to replicate the original mobile phone experience.)

And oh, these games remain remarkable, all these years later. Things begin humbly with Kosmo Spin – a cute little arcade diversion, your only goal a high score. But Simogo’s ambition immediately begins to take shape with its next game, Bumpy Road, another arcade-style game about an old couple on a road trip, but infused with surprising whimsy and melancholy, a minimalist love story there for those who look for it. After this, the studio is off to the races, on an incredible streak of games that extends to this day – the devilish glee of Beat Sneak Bandit giving way to the melancholic, frightening folklore of Year Walk and the slick flair of Device 6.

Simogo’s interests are wide-ranging and interdisciplinary. Flesser and Gardebäck have made a tradition of writing about the influences that inform each of their games, chronicling every project’s origin on their website . As a result, playing a Simogo game feels like getting a letter from some of your most eccentric friends, who, after spending a lot of thinking about Patrick McGoohan’s The Prisoner, the work of graphic designer Sam Suliman, and Nintendo’s Virtual Boy, can’t help but write to you with a prose puzzle riffing on all these things using the typographic experimentation of House of Leaves.

Times have changed, and Simogo has expanded beyond Flesser and Gardebäck as their ambition has grown and brought them back to the realm of console games – such as the playable pop album Sayonara Wild Hearts, and their puzzle-mystery magnum opus Lorelei and the Laser Eyes. The brief, heady days of App Store brilliance are over; the world that allowed Simogo to flourish is now extinct. How fortunate it was that Simogo got the chance they did; that they’re still with us, and able to assemble this inspiring little collection we can play in perpetuity. These games, in all their varied playfulness, are full of longing: for a lover, for meaning, for a chance to write your own ending. Play them and dream about a world where it all went differently.

Short-Circuiting Correlated Subqueries in SQLite

Lobsters
emschwartz.me
2025-12-17 11:27:30
Comments...
Original Article

I recently added domain exclusion lists and paywalled content filtering to Scour . This blog post describes a small but useful SQL(ite) query optimization I came across between the first and final drafts of these features: using an uncorrelated scalar subquery to skip a correlated subquery (if you don't know what that means, I'll explain it below).

Scour searches noisy sources for content related to users' interests. At the time of writing, it ingests between 1 and 3 million pieces of content from over 15,000 sources each month. For better and for worse, Scour does ranking on the fly, so the performance of the ranking database query directly translates to page load time.

The Ranking SQL Query

The main SQL query Scour uses for ranking applies a number of filters and streams the item embeddings through the application code for scoring.

Scour uses brute force search rather than a vector database, which works well enough for now because of three factors:

  1. Scour uses SQLite, so the data is colocated with the application code.
  2. It uses binary-quantized vector embeddings with Hamming Distance comparisons, which only take ~5 nanoseconds each .
  3. We care most about recent posts so we can significantly narrow the search set by publish date.

A simplified version of the query looks something like:

SELECT *
FROM items i
WHERE i.lang IN (SELECT lang FROM user_languages WHERE user_id = ?1)
AND i.published BETWEEN ?2 AND ?3
AND ...(more filters)...

The query plan shows that this makes good use of indexes:

QUERY PLAN
   |--SEARCH i USING INDEX idx_items_lang_published (lang=? AND published>? AND published<?)
   `--LIST SUBQUERY 1
      `--SEARCH user_languages USING COVERING INDEX sqlite_autoindex_user_languages_1 (user_id=?)

Domain Filters Using Correlated Subqueries

To add user-specified domain blocklists, I created the user_excluded_domains table and added this filter clause to the main ranking query:

AND NOT EXISTS (
    SELECT 1
    FROM user_excluded_domains ued
    WHERE user_id = ?1
    AND ued.domain = i.domain
)

The domain exclusion table uses (user_id, domain) as a primary key, so the lookup is efficient. However, this lookup is done for every row returned from the first part of the query. This is a correlated subquery :

QUERY PLAN
   |--SEARCH i USING INDEX idx_items_lang_published (lang=? AND published>? AND published<?)
   |--LIST SUBQUERY 1
   |  `--SEARCH user_languages USING COVERING INDEX sqlite_autoindex_user_languages_1 (user_id=?)
   `--LIST SUBQUERY 2
      `--SEARCH user_excluded_domains USING COVERING INDEX sqlite_autoindex_user_excluded_domains_1 (user_id=?)

A problem with the way we just added this feature is that most users don't exclude any domains, but we've added a check that is run for every row anyway.

To speed up the queries for users who aren't using the feature, we could first check the user's settings and then dynamically build the query. But we don't have to, because we can accomplish the same effect within one static query.

We can change our domain exclusion filter to first check whether the user has any excluded domains:

AND (
    NOT EXISTS (
        SELECT 1
        FROM user_excluded_domains
        WHERE user_id = ?1
    )
    OR NOT EXISTS (
           SELECT 1
           FROM user_excluded_domains ued
           WHERE user_id = ?1
           AND ued.domain = i.domain
    )
)

Since the OR short-circuits, if the first NOT EXISTS returns true (when the user has no excluded domains), SQLite never evaluates the correlated subquery at all.

The first NOT EXISTS clause does not reference any column in items , so SQLite can evaluate it once and reuse the boolean result for all of the rows. This "uncorrelated scalar subquery" is extremely cheap to evaluate and, when it returns true , lets us short-circuit and skip the more expensive correlated subquery that checks each item's domain against the exclusion list.

Here is the query plan for this updated query. Note how the second subquery says SCALAR SUBQUERY , whereas the third one is a CORRELATED SCALAR SUBQUERY . The latter is the per-row check, but it can be skipped by the second subquery.

QUERY PLAN
   |--SEARCH i USING INDEX idx_items_lang_published (lang=? AND published>? AND published<?)
   |--LIST SUBQUERY 1
   |  `--SEARCH user_languages USING COVERING INDEX sqlite_autoindex_user_languages_1 (user_id=?)
   |--SCALAR SUBQUERY 2
   |  `--SEARCH user_excluded_domains USING COVERING INDEX sqlite_autoindex_user_excluded_domains_1 (user_id=?)
   `--CORRELATED SCALAR SUBQUERY 3
      `--SEARCH ued USING COVERING INDEX sqlite_autoindex_user_excluded_domains_1 (user_id=? AND domain=?)

Benchmarking

To test the performance of each of these queries, I replaced the SELECT * with SELECT COUNT(*) and used a simple bash script to invoke the sqlite3 binary 100 times for each query on my laptop. Starting up the sqlite3 process each time adds overhead, but we're comparing relative differences.

At the time of this benchmark, the last week had 235,975 items, 144,229 of which were in English. The two example users I tested this for below only look for English content.

User Without Excluded Domains

This test represents most users, who have not configured any excluded domains:

Approach Min (ms) Max (ms) Avg (ms) Stddev (ms) Diff (ms) Diff (%)
Baseline (no filter) 67 91 72.7 4.7
Correlated Subquery 80 108 85.2 5.5 +12.5 +17.1%
With Short-Circuit 69 91 72.7 3.8 +0 +0%

This shows that the short-circuit query adds practically no overhead for users without excluded domains, whereas the correlated subquery alone makes queries 17% slower for these users.

User with Excluded Domains

This test uses an example user that has excluded content from 2 domains:

Approach Min (ms) Max (ms) Avg (ms) Stddev (ms) Diff (ms) Diff (%)
Baseline (no filter) 68 99 76.2 7.6
Correlated Subquery 84 112 90.5 6.8 +14.3 +18.7%
With Short-Circuit 82 109 88.5 8.1 +12.3 +16.1%

In this case, we do need to check each row against the domain filter. But this shows that the short-circuit still adds no overhead on top of the query.

Conclusion

When using SQL subqueries to filter down result sets, it's worth thinking about whether each subquery is really needed for most users or most queries. If the check is needed most of the time, this approach won't help. However if the per-row check isn't always needed, using an uncorrelated scalar subquery to short-circuit a condition can dramatically speed up the average case with practically zero overhead.

This is extra important because the slow-down from each additional subquery compounds. In this blog post, I described and benchmarked a single additional filter. But this is only one of multiple subquery filters.

Earlier, I also mentioned that users had asked for a way to filter out paywalled content. This works similarly to filtering out content from excluded domains. Some users opt-in to hiding paywalled content. For those users, we check if each item is paywalled. If so, we check if it comes from a site the user has specifically allowed paywalled content from (because they have a subscription). I used the same uncorrelated subquery approach to first check if the feature is enabled for the user and, only then, does SQLite need to check each row.

Concretely, the paywalled content filter subquery looks like:

AND (
    (
        SELECT COALESCE(hide_paywalled_content, 0) = 0
        FROM users
        WHERE user_id = ?1
    ) -- note these parentheses are needed so SQLite doesn't mistakenly think this query is correlated with `items`
    OR COALESCE(i.is_paywalled, 0) = 0
    OR i.domain IN (
        SELECT domain
        FROM user_paywall_allowed_domains
        WHERE user_id = ?1
    )
)

In short, a trivial uncorrelated scalar subquery can help us short-circuit and avoid a more expensive per-row check when we don't need it.

Appendix: NOT EXISTS vs NOT IN vs LEFT JOIN

There are multiple ways to exclude rows from an SQL query.

Here are the results from the same benchmark I ran above, but with two other ways of checking for whether an item comes from an excluded domain.

The NULL-safe NOT IN version of the query uses the subquery:

...
AND (
    i.domain IS NULL
    OR i.domain NOT IN (
        SELECT domain
        FROM user_excluded_domains
        WHERE user_id = ?1
    )
)

The LEFT JOIN variation joins items with user_excluded_domains and then checks for NULL :

SELECT *
FROM items i
LEFT JOIN user_excluded_domains ued on ued.user_id = ?1 AND ued.domain = i.domain
WHERE i.lang IN (SELECT lang FROM user_languages WHERE user_id = ?1)
AND i.published BETWEEN ?2 AND ?3
AND ued.domain IS NULL

And here are the full benchmarks:

User Without Excluded Domains

Approach Min (ms) Max (ms) Avg (ms) Stddev (ms) Diff (ms) Diff (%)
Baseline (no filter) 67 91 72.7 4.7
NOT EXISTS (no short-circuit) 80 108 85.2 5.5 +12.5 +17.1%
NOT EXISTS + short-circuit 69 91 72.7 3.8 +0 +0%
NULL-safe NOT IN (no short-circuit) 75 111 79.5 7.1 +6.8 +9.3%
NULL-safe NOT IN + short-circuit 69 103 74.8 6.6 +2.1 +2.8%
LEFT JOIN (no short-circuit) 74 100 79.1 5.1 +6.4 +8.8%
LEFT JOIN + short-circuit 76 103 84.4 7.4 +11.7 +16.0%

For users without excluded domains, we can see that the NOT EXISTS query using the short-circuit wins and adds no overhead.

User With Excluded Domains

Approach Min (ms) Max (ms) Avg (ms) Stddev (ms) Diff (ms) Diff (%)
Baseline (no filter) 68 99 76.2 7.6
NOT EXISTS (no short-circuit) 84 112 90.5 6.8 +14.3 +18.7%
NOT EXISTS + short-circuit 82 109 88.5 8.1 +12.3 +16.1%
NULL-safe NOT IN (no short-circuit) 83 112 89.7 8.4 +13.5 +17.7%
NULL-safe NOT IN + short-circuit 84 112 91.3 8.2 +15.1 +19.8%
LEFT JOIN (no short-circuit) 81 107 86.3 6.7 +10.1 +13.2%
LEFT JOIN + short-circuit 82 126 89.8 7.7 +13.6 +17.8%

For users who do have excluded domains, the LEFT JOIN is faster than the NOT EXISTS version. However, this version raises the exact problem this whole blog post is designed to address. Since joins happen no matter what, we cannot use the short-circuit to avoid the overhead for users without excluded domains. At least for now, this is why I've gone with the NOT EXISTS subquery using the short-circuit.

#scour

Ghost jobs, robot gatekeepers and AI interviewers: let me tell you about the bleak new age of job hunting | Eleanor Margolis

Guardian
www.theguardian.com
2025-12-17 11:00:32
In my six months of looking for work, I’ve found that from fake ads to AI screening software, the search is more soul-destroying than ever As I apply for yet another job, I look at the company’s website for context. I’ve now read their “what we do” section four or five times, and I have a problem –...
Original Article

A s I apply for yet another job, I look at the company’s website for context. I’ve now read their “what we do” section four or five times, and I have a problem – I can’t figure out what they do. There are two possibilities here. One: they don’t know what they do. Two: what they do is so pointless and embarrassing that they dare not spell it out in plain English. “We forge marketing systems at the forefront of the online wellness space” translates to something like “we use ChatGPT to sell dodgy supplements”.

But understanding what so many businesses actually do is the least of my worries. I’m currently among the 5% of Brits who are unemployed. In my six months of job hunting, my total lack of success has begun to make me question my own existence. Just like when you repeat a word over and over until it loses all meaning, when you apply repeatedly for jobs in a similar field, the semantics of the entire situation begin to fall apart like a snotty tissue. About one in five of my job applications elicit a rejection email, usually bemoaning the sheer number of “quality applicants” for the position. For the most part, though – nothing. It’s almost like the job never existed in the first place, and it’s possible that it didn’t.

In 2024, 40% of companies posted listings for “ghost jobs ”, nonexistent positions advertised to create the illusion that the company is doing well enough to take on new employees. And this seems like an all-too-easy way to lie about your success. Regulation of job ads is mostly the remit of the Advertising Standards Authority, which – in all its might – has the power to … have a misleading job ad taken down. So with no particularly harsh consequences for employers, why not go on a pretend hiring spree? Ethics in the job market seem to have gone out the window, and the idea of wasting the time of thousands of hapless jobseekers doesn’t seem to matter much.

Even if the job you’re applying for exists, next comes the hurdle of the AI HR bot. While it’s difficult to find any hard data on just how many employers are using AI to filter applications (sometimes favouring men over women, if a now-scrapped algorithm used by Amazon is anything to go by), articles and Reddit threads about how to game the bots and get in the right “key words” now abound. According to an Atlantic article from earlier this year: “Young people are using ChatGPT to write their applications; HR is using AI to read them; no one is getting hired.” And let’s say your CV and cover letter do make it past the robot gatekeepers, it’s possible that your interview will be conducted by yet another bot . Although I haven’t had the pleasure of an interview, AI or otherwise, since I began my latest job search, the possibility of not coming into contact with a single human during most of the process to becoming the dodgy supplements social media marketing manager looms large and dreadful.

While this scramble for jobs is mostly being framed as a problem for graduates , I can confirm – as someone who graduated 15 years ago bang into a recession – not only is this the worst job market I’ve ever seen, but it’s also impacting people like me with many years’ experience. During my last period of job hunting, about three years ago, I was at least getting interviews. Interviews with humans, to boot. Given all the skilled people I know who can’t seem to land interviews for even entry-level positions, I’m certain that I’m not an outlier. I’m also convinced that we’re facing a crisis in which middle-class jobs have mutated into rare and disturbing beasts.

When, according to its job ad, an indie pet food company called something like Flopsies is looking for a “rock star” and a “unicorn” to revolutionise its social media presence, you know that the job market has become high on its own farts. Ill-defined franken-jobs, requiring everything from SEO expertise to video-editing skills (all for a salary of £27,000 and free protein bars that taste like hay) require cult-like dedication. First, you must convince the fine people at Flopsies that it has been your dream since exiting your mother’s birth canal to sell pet food. You would cut off your own hands for the privilege, and quickly learn to write copy for them by smashing your face into a keyboard. You will convey this in a 400-word cover letter, written in your own blood. This cover letter will then be redirected into the ether by an AI filter, because you didn’t use the phrase “optimising algorithmic relevancy” in it. You will never hear from Flopsies again. You will start this process again and repeat it until you are seen fit for an interview in which you have a few minutes to convince a bot that you’re fit for purpose as both a worker and a human being.

The hiring process has become so mechanised, both figuratively and literally, that it’s hard to believe that the people who end up being hired aren’t merely the best at gaming the system. And frankly, all power to them. It’s no skin off my nose if the dodgy supplement or pet-food jobs go to people who are incredible at creating the illusion that they live and breathe pet food and/or dodgy supplements. But in this oh-so-streamlined process, what happens to those of us who can’t or won’t play the game? Of all the applications I’ve sent out recently, I wonder how many have been looked at by humans. There’s only so much shouting into the void about your ability to use a CMS you can do before you give up and start Googling things like: “Can I sell a kidney on Vinted?”

  • Eleanor Margolis is a columnist for the i newspaper and Diva

‘Music needs a human component to be of any value’: Guardian readers on the growing use of AI in music

Guardian
www.theguardian.com
2025-12-17 11:00:31
AI promises to have far-reaching effects in music-making. While some welcome it as a compositional tool, many have deep concerns. Here are some of your responses AI-generated music is flooding streaming platforms, and it seems to be here to stay. Last month, three AI songs reached the highest spots ...
Original Article

A I-generated music is flooding streaming platforms, and it seems to be here to stay. Last month, three AI songs reached the highest spots on Spotify and Billboard charts . Jorja Smith’s label has called for her to receive a share of royalties from a song thought to have trained its original AI-generated vocals on her catalogue , which were later re-recorded by a human singer.

With this in mind, we asked for your thoughts on music composed by AI, the use of AI as a tool in the creation of music, and what should be done to protect musicians. Here are some of your responses.

‘There was one song I actually liked’

I have already found AI songs being added into jazz playlists and “radio stations” on Spotify. There was one song I actually liked, so I did some digging and found out it was a group with a generic name that had around three to five albums all released in 2025. Then I noticed the next track and the track followed the same path. It was really irksome. History, I hope, shows that people do value human flaws in art. Sometimes it helps us feel seen or not alone. I don’t understand how a completely computer-generated sound based on what’s come before could do that. Then again, some people fall in love with LLMs . I just think everything should be labelled somehow. Give people the choice. Make sure there are protections in place like forcing social feeds and music platforms to give consumers the ability to filter out AI-generated content. Casey , 37, Chicago, US

‘There’s no heart in music generated by AI’

There’s no heart in music generated entirely by AI, and encouraging it is hurting the livelihoods of musicians. It is also very important not to call music made by AI “composed”. That word gives AI prompters far more credit and muddies the waters as to what composition is. The only people served by AI music are companies like Spotify, and major record labels who would no doubt rather not have to pay artists at all.

As for working with AI, I once recorded an album with my band and lost the stem tracks before we finished the final mix, but we were able to use an AI tool that could isolate certain instruments in the masters and boost them to get the mix we wanted. That seems to me an example of positive AI usage, and something that wouldn’t have been possible before AI. A composer like Ben Nobuto is also an example of someone who has used AI as a starting point for building real, human music. It’s probably too late now, but all musicians with work on streaming sites should probably have been paid as their work was likely used as training data. Additionally, musicians should be able to opt out of their work being used to train LLMs just like cookies on a website. Jon, 30, musician and music teacher, Switzerland

I believe music needs a human component to be of any value. Music composed by AI has, from what I have heard, a big problem with simplistic or visible lyrics and a lack of emotional content.

But I am happy with musicians using AI as a tool. It brings professional quality recordings to those unable to hire a studio, orchestra or vocalist and so on. I have been writing songs for decades – in the 80s I couldn’t afford a Portastudio (four-track cassette recorder), so I used two single-track machines instead to play and record simultaneously. Now I can upload my songs to Suno (a generative AI program) and create new arrangements of them close to my original intention. It is great to be able to write for voices other than my own. Even so, some of my family and friends tell me they prefer my original versions. Mike Lee, 67, ex-photographer and teacher, Southampton

AI-generated band Velvet Sundown.
Less than fab … AI-generated band Velvet Sundown. Illustration: Velvet Sundown

‘It’s stopping creativity’

AI-generated music is a copyright nightmare and is stopping creativity. We don’t have to accept it, and we don’t have to use it. The most irksome thing is non-creatives believing themselves to be artists, using AI to create and claiming it as their own art, when it’s an amalgamation of stolen work. Not sculpted with their own hands, not conceived in their own minds. Frankly, I find it embarrassing when someone proudly declares using it. Artists are already marginalised, but there is a kickback against, for example, TV slop, and a growing demand for audiences – in all forms – to not be treated like idiots. Artists are the answer to this, not AI.

If you can harness it to your advantage as an assistive tool, then by all means use it. The danger is to become reliant on AI. There should be a clear payment scheme, similar to PRS and PPL where AI shows exactly which items have been used to create. Or a watermark on copyrighted material. Nicole Vardon-Martin, 37, events and stage manager, Dagenham

When social media and streaming services are flooded with digitally regurgitated stuff, it becomes harder to find the pieces with personal decisions behind them. I like knowing there’s a story behind the songs I get stuck in my head. I don’t think generative AI is the neutral tool many describe it to be, both because of its strain on the earth and because anything used by these algorithms has to come from somewhere, and keep coming, for what they chuck together to seem original.

Blatantly copying someone else’s work doesn’t become “taking inspiration” because some software has mixed it around. Yes, there are musicians who use only their own work to generate “new” music, but in my opinion this is quite an insular and thoughtless way of creating. Generative AI will always, eventually, become bland without new content to sustain it, and more AI-generated work cannot fill that void. Charlotte, student, Cornwall

‘I worry I would become dependent on the technology’

In my home studio I use AI to help mix and master music. I can see that it might be tempting to use an AI voice on your composition if you can’t sing – but why not go out to an open mic and see if you can find a real, living voice? Where would Burt Bacharach and Hal David be without all the brilliant singers who interpreted their songs? Who knows what a real musician will add to your music.

I might be tempted to use AI to write a song but then I suspect my own musical abilities would atrophy and I would become quickly dependent on the technology. I don’t know enough about how copyright would work in these circumstances, but we need to protect human creativity and one way is to go out and see live music, commission people to write it, and to buy music directly from the artist if you can, avoiding those streaming services that pay very little and seem to be actively promoting fake artist profiles. Geoff Smith, 65, musician and retired headteacher, Cornwall

Show HN: Mephisto – A RAM-only, ad-free disposable email PWA built with React

Hacker News
mephistomail.site
2025-12-17 09:54:48
Comments...

Is Mozilla trying hard to kill itself?

Hacker News
infosec.press
2025-12-17 09:37:24
Comments...
Original Article

In an interview with “The Verge”, the new Mozilla CEO, Enzor-DeMeo, IMHO hints that axing adblockers is something that, at the very least, was on the table in some form and at some point. From the article :

He says he could begin to block ad blockers in Firefox and estimates that’d bring in another $150 million, but he doesn’t want to do that. It feels off-mission.

It may be just me, but I read this as “I don't want to 😜 😜 but I'll kill AdBlockers in Firefox for buckerinos 😂”. This disappoints and saddens me a lot, and I hope I'm wrong.

I've been using Firefox before it was called that. Heck, I even used the Mozilla Application Suite back in the day. It was its commitment to open standards and the open web, and its powerful add-on system, that attracted me to its software.

Honestly, that's what's been keeping me. I think that's also what's been keeping their loyal base of users with the project, the geeks and nerds that care about privacy. It's the same group of people who helped it get very popular at one point.

Killing one of its advantages over the Chromium engine, being able to have a fucking adblocker that's actually useful, and that nowadays is a fucking security feature due to malvertising, will be another nail in the coffin, IMHO. The core community will feel disenfranchised, and this may have negative consequences for the project. You know why? Because these are some of the people that the normies turn to when they want tech advice.

For fuck sake, for-profit side of Mozilla, get a damn grip!

# Mozilla # Firefox # AdBlocker # OpenSource # FOSS

A Survey of Dynamic Array Structures

Lobsters
azmr.uk
2025-12-17 09:29:30
Comments...
Original Article

This is a more thorough coverage of one of the topics that came up in my recent BSC25 talk "Assuming As Much As Possible"

You use arrays all the time.
The number of elements they need is often determined at runtime.
There many different alternatives for representing these, with different characteristics. Let's discuss these .

Caveats
  • This is written by someone who tries to avoid general purpose allocators, mostly using arenas instead. I may miss some subtleties of use with GP allocation.
  • I am not perfectly representing the entire design space, but picking representative points. Let me know if you feel I missed any significant alternatives.

First... you may not actually need a fully-dynamic array, so let's start with some not-quite-dynamic options that may be useful if you can get away with them.

Statically fixed-size array

Even if you don't know the exact number of elements, you may be able to set a reasonable upper bound and keep arrays of that fixed length.

Pros

  • Easy to reason about
  • No dynamic allocation
  • Can store inline in structures (0 indirection)

Cons

  • If your number of elements is highly-variable, the number of array slots you waste ends up dominating the actually-used slots. i.e. they become very inefficient.
  • Difficult to reason about if length is user-controlled (and you aren't able to limit them).
  • Array size is fixed after init; if you don't account for enough elements your program you either need additional handling or you enter an invalid state.

Runtime fixed-size array

Maybe you don't know the length at compile time, but at runtime you can work out how big some variably-sized data is before you allocate, so you just allocate a fixed block on an arena somewhere.
Importantly the array doesn't grow (beyond some accounted-for factor) after the initial allocation.

There's a variant of this where you effectively do some variable-length work twice: one going through the motions but not doing anything with the data, just to determine the length, and then a second time after allocating where you actually put the data in-place.

This is functionally the same as the static variant. Typically this will use an extra indirection, however you can allocate a struct as a header immediately before a runtime-sized array, which is sometimes called a "struct hack". In this case the data is offset from the header rather than being a "real" pointer indirection.

realloc -style double-and-copy array

Ok, now for the real dynamic arrays. We'll start with what is probably most developers' default structure.

Maintain a buffer with a particular capacity. When the length of the array exceeds the capacity you allocate a new buffer that is some factor larger than the original one (e.g. 2x the size, golden ratio times the size...), copy all the members over.

Variants of this include storing the capacity/length either at the start of the buffer or externally. If storing at the start, another variant is the STB-style header, where you store a pointer to the data, then do pointer arithmetic to find the metadata.

Pros

  • Imposes minimal constraints; very general purpose
  • Contiguous data
  • "Amortized O(1) growth"
  • Familiar to most developers

Cons

  • Spiky latency: normally fine until you hit the growth point, then you have to allocate (possibly moderately expensive, depending on allocator) and copy potentially large amounts of data
  • You can't take pointers to the array members that are stable across pushes to the array. You have to use indices instead.
  • Either leaks memory or requires a moderately complex allocator
    e.g. malloc/power-of-2 freelists/buddy allocator
  • These in-turn complicate use...

Aside 1: why is the allocation pattern a big deal?

When you resize the array, there is a choice about what to do with the old buffer. Options include:
A : Leak the memory, either indefinitely or until a later arena pop/clear.
B : free the buffer to your on-arena power-of-2 pool freelist.
C : free the buffer to a general-purpose allocator

A is nice and simple, but you approach 50% fragmentation as the best case occupancy. This is probably fine for short-lived or small arrays, but isn't great in the general case.

B uses the memory more efficiently, but if you're freeing to a list, you're almost certainly also allocating from them as well. This makes it non-obvious where the data for your next allocation will come from. If you're treating your arena as a stack, beware that pools and stacks interact badly unless you're very careful. (See Aside 3 for a similar error, bearing in mind that freeing involves appending data to a discontiguous list and is analogous to the array push there.)

C avoids you having to think about these things... but you're using a general-purpose allocator, so you miss out on all the arena advantages, it's also moderately slow and hard to reason about when you end up needing to.

Any non-trivial allocation seems to end up with treating the array as an invidual element, that you then have to individually free (unless you clear the entire freelist pool), negating the benefits of grouped lifetimes on an arena.

You can no longer do the really useful pattern of:

  • Get current arena location
  • Do a bunch of stuff that includes arbitrary allocation
  • Pop arena back to initial location

Aside 2: what's wrong with using indices?

I'm not anti-index, they're better than pointers for a few particular use-cases (out-of-scope here). However, being forced to use them does come with some downsides:

  • You need to provide some means of accessing the base of the array.
  • You now have the potential to index into the wrong array, possibly an array of a different type.
  • For a single array access you now have to provide 2 pieces of data instead of just 1 (e.g. in structs, parameter lists), which is sometimes a bit of a pain, but normally manageable.
    • Indices in structs can't be auto-dereferenced by debuggers (without additional markup describing a base expression). This adds extra friction to following references.
  • If you have nested arrays inside of arrays inside of arrays, all with unstable pointers, you need a piece of data for each step in this chain to stably & uniquely identify a leaf element. This becomes considerably annoying to write code for, and also uses a significant factor more memory if you need a lot of references to these leaf elements.
    (I mention hitting this nested case in WhiteBox in the talk.)

Arena-backed array

Uses virtual memory tricks to reserve a very large contiguous address range that won't be backed by actual memory unless it's used.

This can take the form of either:

  • An entire arena dedicated to one array, which is a special-case of:
  • All pushes of members to this array are simplex (i.e. not interleaved with pushing anything else onto the arena), so they're always occurring at the end of an arena.

Pros

  • Contiguous address space - easy to reason about
  • Doesn't use memory that isn't required

Non-issues

  • On 64-bit systems the address space is very large, so you're unlikely to run out

Cons

  • Each arena needs to be freed individually, so you want a small, tractable number. This limits how many arrays you want to be fully backed by arenas.
  • Avoiding interleaving is only practical in certain circumstances. You need as many arenas as you have interleaved pushes.

Chunk/Bucket arrays

Your array is effectively split into chunks of (typically) even size that contain the actual data.
You then add a layer of metadata: a separate array of pointers, pointing to the start of each subsequent block.
The chunks remain stable while the metadata moves around like a normal realloc array.

Pros

  • Stable pointers
  • No data copying required, leaving allocation as the main source of latency spikes.

Non-issues

  • It doesn't matter that the metadata is unstable because nothing outside the array needs to take pointers to it
  • Contiguous data within chunks means that cache efficiency can stay high.
  • Still has O(1) access to any of the members: just a divmod of the chunk size to determine which pointer & then the offset within the chunk.
    (if you choose a power of 2 this becomes a shift and an AND, which are very cheap operations)

Cons

  • O(N) metadata
  • This basically inherits all of the issues of the realloc -style array , but scaled down by the constant factor of the chunk size
  • As the elements are no longer contiguous you lose the ability to easily make subslices or determine the distance between 2 element pointers by simple subtraction.
  • Although the pointer instability is a non-issue, the bookkeeping & allocator work for the metadata are non-trivial
  • 2 levels of indirection: to the metadata, then through to the pointer chunks

Aside 3: who cares if the elements aren't contiguous?

When you have discontiguous chunks, you run into a few issues.

Slices

With contiguous arrays, you can make a {length, pointer} slice of arbitrary subsections of data with no allocation or extra work required.
Significantly, you can treat slices of the full structure or of any subsection equivalently.

Once you have chunks, unless you have a structure designed with this specifically in mind, you lose the ability to easily make slices. It's not just that you can't take a pointer + length because there may be a gap, although this is the first issue you hit. The presence of the chunks and the fact they have either assumed size or chunk-header size data makes it meaningfully different to point to an element at the start of the chunk or the end of the chunk.

You can always fall back to "full container structure (pointer/copy) + start & end indices", although this is a bit clunky.

Distances are no longer meaningful

With a simple array, you can subtract the pointer of one element from another to find the displacement/distance between the 2. The most obvious place this is useful is that you can subtract the base from an arbitrary member to find its index.

This does not apply if there are gaps in the middle of the array. It's not that it's impossible to compute an index from a pointer, but it's now a thing , it needs to look at metadata, probably with loops and memory indirection and function calls... not just a trivial subtraction.

New opportunity for error

This is possibly one of the few error modes that are more likely with an arena than with general-purpose memory management. The issue arises when you're using the arena as a stack and aren't sufficiently careful about not interleaving array pushes & accesses with arena pops. This is probably best illustrated with an example:

DiscontiguousArray arr = {0};
for (int i = 0; i < n; ++i)
{
    push_onto_arr(&arena, &arr, some_other_data[i]);
}

UPtr arena_checkpoint = arena_get_checkpoint(&arena);
// ...
push_onto_arr(&arena, &arr, more_data); // BAD
// ...
pop_to_checkpoint(&arena, arena_checkpoint);

Thing new_thing = arena_push_data(&arena, sizeof(thing), &thing); // CLOBBER
do_something_with_arr(&arr); // INVALID

The array now may have chunks that are not in the allocated memory of the arena, so new arena pushes can return that same memory to be overwritten for completely different purposes. This means that the last element could be corrupted. This is, in effect, a special case of use-after-free that the split structure enables. From the arena's perspective we're misusing its stack.

A hazard here is that this will fail inconsistently and potentially silently. There is only a visible error if pushing the member in the BAD line allocates a new chunk. If the chunk allocated before the checkpoint isn't full, then the new element goes into "safe" memory. Separately, if you don't push any other data and you don't invalidate the "freed" arena memory, you'll read it without issue... this time.

I don't want to overstate this: I think I've hit this error once, maybe twice, but it is something to be aware of. ASan poisoning or clearing popped arena memory to known-garbage data (e.g. memset(0xcc) ) in debug mode will also make it loud in many cases.

Linked chunks

Keep pointers to just the first and last chunk, then have each chunk point to the one that comes after it. Chunk sizes could be fixed or dynamic, with a size header at the beginning of each chunk.
(Normal linked lists are a special-case of this where chunk_n == 1 )

Pros

  • Minimally-complicated bookkeeping structures or code
  • Large enough chunks can provide reasonable cache usage
  • Trivial to allocate on arenas
  • Trivial iteration

Cons

  • O(N) metadata
  • O(N) random access

Good for traverse-only structures. (We use them for string lists in WhiteBox).

Tree

Taking the metadata layering of chunk arrays to its logical extent, and making it recursive.

There are many different implementations, and fully differentiating all the options is way out-of-scope here. They'll mostly have the same characteristics for our purposes here.
A couple of significant variants:

  • All data in leaf nodes vs data in leaf AND inner nodes
  • Fixed/variable branching factors (i.e. how many child nodes does each node have)
  • All leaf nodes at the same depth vs variable-height subtrees.
  • Skip lists are a notable oddity that are more like the linked chunks than the chunk array.

Pros

  • Pretty good at everything: commonly O(log(N)) for most operations (read/write/insert/update/...)
  • Can have holes in the middle of your index space if your members are sparse.
  • Can use "structural sharing" to deduplicate data within or across arrays (if you can make assumptions about data immutability).

Cons

  • Not great at anything
  • Lots of indirection
    • This can be reduced in some circumstances at the cost of complexity
  • Design work required to be cache efficient
  • Significant stored metadata
  • Significant bookkeeping
    • O(N) metadata
  • Moderately complicated work for accessing/modifying/iterating

Exponential Array - Xar

Use a fixed inline array of pointers to exponentially-growing chunks. (Watch for the upcoming article for a detailed explanation.)

Pros

  • Minimal bookkeeping
  • Only 1 level of indirection
  • Trivial arena allocation pattern
  • O(1)/fixed-size metadata
    • Useful information (e.g. max capacity, size of chunk X, ...) knowable at compile-time, which both makes it predictable as a user, and allows the compiler to perform optimizations relying on that information.

    • (In the theoretical general case it's O(log(N)), but it's easy to find a reasonable upper bound when you can double the capacity by adding a pointer)

  • Minimal work on access (uses bitwise operations, no loops) & iteration.

Cons

  • Each array struct is moderately large (~8-30 pointers). This is normally insignificant unless you have a huge number of these arrays that are close-to-empty.
  • Inherits all discontiguous array issues (e.g. Aside 3 )
  • Can't really have holes: as the later chunks are the size of the sum of all preceding chunks, you can never be more than 50% sparse on memory for a given capacity.

(I implemented a slight generalization of this structure that treats subslices and the full data isomorphically - perhaps unsurprisingly called "Exponential Slice"/ Xsl - but I haven't had the need to use it yet, and it comes with at least some extra complexity.)


This covers the span of the available options I am aware of. (If readers know of any viable alternatives that don't fit into the above archetypes I'd be interested to hear about them.)
Let's summarize these...

Comparison table

Columns are options, rows are consideratione:

Thanks to Judah Caruso for feedback on drafts of this post .

Amber-Lang - Bash Transpiler is looking for Rust contributors

Lobsters
lobste.rs
2025-12-17 09:21:54
Hi Lobste.rs! I am one of the project maintainers (but I am not skilled so much in Rust) but the project is build in Rust and we are at 0.5.1 release. It is a compiler to Bash 3.2-5.3 with a dedicated syntax focused to be easy but also including type checking and a set of already implemented and bat...
Original Article

Hi Lobste.rs!

I am one of the project maintainers (but I am not skilled so much in Rust) but the project is build in Rust and we are at 0.5.1 release.

It is a compiler to Bash 3.2-5.3 with a dedicated syntax focused to be easy but also including type checking and a set of already implemented and battle-tested functions.

We are working to get a Bash feature parity (we are missing pipes as example), improve the bash code quality (using ShellCheck), bash performance (we are removing subshells where they are not needed), code coverage (we have also tests for our Amber syntax and functions) and in the future to split the compiler from the cli (so we can target WebAssembly).

One of our idea is to fine-tune a LLM to provide a free AI to convert your bash/python scripts or help you write Amber itself (we have already the hosting for that but we are missing the model).

We have various issues for newcomers but also for Rust skilled contributors, so if you are looking to something to do in your free time, we are here :-D

Docs: https://docs.amber-lang.com/

GitHub: https://github.com/amber-lang

Keeping secrets, or (less than two weeks ago)

Lobsters
kellett.im
2025-12-17 08:49:35
Comments...
Original Article

If you've used IRC in the last few years there's a good chance you have seen this before:

- Last seen  : (about 28 weeks ago)
- User seen  : (less than two weeks ago)

What does “about” mean here, exactly? Why less than two?

This is, of course, a privacy feature, designed so that a third party can tell when someone was around, but only approximately ; they should never learn the exact moment someone signed off. 1

One might imagine, then, that “about 28 weeks ago” is an exact time duration, rounded to the nearest whole number of weeks. But although seeing the rounded number once gives you only approximate information, you could defeat rounding by querying repeatedly until you saw the number tick over.

The solution is to reduce the precision of the last-seen time itself, rather than that of the time duration. Since any given time will only ever round one way, doing it multiple times can’t possibly reveal any extra information.

The way this is done on Libera means all obfuscated last-seen times increment together. Time started on a Thursday and if you NS INFO an unused account you will indeed find that it gets one week more unused every Thursday. 2

But why “less than two”? What’s wrong with “one”?

Actually, one is fine. But if you could see one, you would also sometimes see zero—meaning someone was last seen in a week that hasn’t finished happening yet. That is fairly precise information near the beginning of the week!

So the system has to display zero and one the same way. It seemed odd to describe someone who just left as being seen “about a week ago”, so “less than two” it had to be.

kris: Cross-compile Janet projects with Zig

Lobsters
github.com
2025-12-17 08:45:33
Comments...
Original Article

Kris

Kris is a tool for cross-compiling Janet projects for multiple platforms using Zig.

Usage: kris <subcommand> [<args>]

A tool for cross-compiling Janet projects for multiple platforms using Zig.

Options:

 -h, --help    Show this help message.

Subcommands:

 c, clean        Delete the kris cache directory.
 j, janet        Cross-compile Janet.
 q, quickbin     Cross-compile a standalone executable.

For more information on each subcommand, type 'kris help <subcommand>'.

Requirements

Kris requires GNU Make and Zig to be installed and available on your PATH. Zig is used to cross-compile for different target platforms.

Installing

Jeep

If you use Janet, you can install kris using Jeep :

$ jeep install https://github.com/pyrmont/kris

From Source

To install the kris binary from source, you need Janet installed on your system. Then run:

$ git clone https://github.com/pyrmont/kris
$ cd kris
$ git tag --sort=creatordate
$ git checkout <version> # check out the latest tagged version
$ janet --install .

Using

Run kris --help for usage information.

Cross-Compiling Janet

Cross-compile Janet for a specific platform:

$ kris janet --target linux-x64 --version 1.40.1

Supported targets:

  • native - Your current platform
  • linux-x64 - Linux x86-64
  • linux-arm64 - Linux ARM64
  • macos-x64 - macOS x86-64
  • macos-arm64 - macOS ARM64
  • windows-x64 - Windows x86-64
  • windows-arm64 - Windows ARM64

By default, kris uses the latest release from the Janet repository. You can specify a specific version with --version .

To optimize for smallest binary size, use the --small flag:

Creating Quickbins

Create a standalone executable from a Janet script:

$ kris quickbin script.janet output

This embeds your Janet script's bytecode into a standalone executable that includes the Janet runtime.

You can target different platforms:

$ kris quickbin --target linux-x64 script.janet output

As with the janet subcommand, you can optimize for smallest binary size, use the --small flag:

$ kris quickbin --small script.janet output

Cleaning the Cache

Kris caches Janet source code and build artifacts in ~/.cache/kris (or $XDG_CACHE_HOME/kris ). To clean the cache:

Bugs

Found a bug? I'd love to know about it. The best way is to report your bug in the Issues section on GitHub.

Licence

Kris is licensed under the MIT Licence. See LICENSE for more details.

AI's real superpower: consuming, not creating

Hacker News
msanroman.io
2025-12-17 08:34:00
Comments...
Original Article
October 30, 2025

Everyone's using AI wrong. Including me, until last month.

We ask AI to write emails, generate reports, create content. But that's like using a supercomputer as a typewriter. The real breakthrough happened when I flipped my entire approach.

AI's superpower isn't creation. It's consumption.

The creation trap

Here's how most people use AI:

  • "Write a blog post about engineering leadership"
  • "Generate code for this feature"
  • "Create a summary of this meeting"

Makes sense. These tasks save time. But they're thinking too small.

My Obsidian vault contains: → 3 years of daily engineering notes → 500+ meeting reflections → Thousands of fleeting observations about building software → Every book highlight and conference insight I've captured

No human could read all of this in a lifetime. AI consumes it in seconds.

The consumption breakthrough

Last month I connected my Obsidian vault to AI. The questions changed completely:

Instead of "Write me something new" I ask "What have I already discovered?"

Real examples from this week:

"What patterns emerge from my last 50 one-on-ones?" AI found that performance issues always preceded tool complaints by 2-3 weeks. I'd never connected those dots.

"How has my thinking about technical debt evolved?" Turns out I went from seeing it as "things to fix" to "information about system evolution" around March 2023. Forgotten paradigm shift.

"Find connections between Buffer's API design and my carpeta.app architecture" Surfaced 12 design decisions I'm unconsciously repeating. Some good. Some I need to rethink.

Your knowledge compounds, but only if accessible

Every meeting, every shower thought, every debugging session teaches you something. But that knowledge is worthless if you can't retrieve it.

Traditional search fails because you need to remember exact words. Your brain fails because it wasn't designed to store everything.

AI changes the retrieval game: → Query by concept, not keywords → Find patterns across years, not just documents → Connect ideas that were separated by time and context

The constraint was never writing. Humans are already good at creating when they have the right inputs.

The constraint was always consumption. Reading everything. Remembering everything. Connecting everything.

Building your consumption system

My setup is deceptively simple:

  1. Everything goes into Obsidian (meetings, thoughts, reflections)
  2. AI has access to the entire vault
  3. I query my past self like a research assistant

But the magic isn't in the tools. It's in the mindset shift.

Stop thinking of AI as a creator. Start thinking of it as the ultimate reader of your experience.

Every note becomes a future insight. Every reflection becomes searchable wisdom. Every random observation might be the missing piece for tomorrow's problem.

The compound effect

After two months of this approach:

→ I solve problems faster by finding similar past situations → I make better decisions by accessing forgotten context → I see patterns that were invisible when scattered across time

Your experience is your competitive advantage. But only if you can access it.

Most people are sitting on goldmines of insight, locked away in notebooks, random files, and fading memories. AI turns that locked vault into a queryable database of your own expertise.

The real revolution

We're still thinking about AI like it's 2023. Writing assistants. Code generators. Content creators.

The real revolution is AI as the reader of everything you've ever thought.

And that changes everything about how we should capture knowledge today.

Start documenting. Not for others. For your future self and the AI that will help you remember what you've forgotten you know.


This piece originally appeared in my weekly newsletter . Subscribe for insights on thinking differently about work, technology, and what's actually possible.

AI and GNOME Shell Extensions

Lobsters
blogs.gnome.org
2025-12-17 08:08:25
Comments...
Original Article

Since I joined the extensions team, I’ve only had one goal in mind. Making the extension developers’ job easier by providing them documentation and help.

I started with the port guide and then I became involved in the reviews by providing developers code samples, mentioning best practices, even fixing the issue myself and sending them merge requests. Andy Holmes and I spent a lot of time writing all the necessary documentation for the extension developers. We even made the review guidelines very strict and easy to understand with code samples.

Today, extension developers have all the documentation to start with extensions, a port guide to port their extensions, and a very friendly place on the GNOME Extensions Matrix channel to ask questions and get fast answers. Now, we have a very strong community for GNOME Shell extensions that can easily overcome all the difficulties of learning and changes.

The number of submitted packages to EGO is growing every month and we see more and more people joining the extensions community to create their own extensions. Some days, I spend more than 6 hours a day reviewing over 15,000 lines of extension code and answering the community.

In the past two months, we have received many new extensions on EGO. This is a good thing since it can make the extensions community grow even more, but there is one issue with some packages. Some devs are using AI without understanding the code.

This has led to receiving packages with many unnecessary lines and bad practices. And once a bad practice is introduced in one package, it can create a domino effect, appearing on other extensions. That alone has increased the waiting time for all packages to be reviewed.

At the start, I was really curious about the increase in unnecessary try-catch block usage in many new extensions submitted on EGO. So I asked, and they answered that it is coming from AI.

Just to give you a gist of how these unnecessary code might look:

destroy() {
    try {
        if (typeof super.destroy === 'function') {
            super.destroy();
        }
    } catch (e) {
        console.warn(`${e.message}`);
    }
}

Instead of simply calling `super.destroy()`, which you clearly know exists in the parent:

destroy() {
    super.destroy();
}

At this point, we have to add a new rule to the EGO review guidelines. So the packages with unnecessary code that indicate they are AI-generated will be rejected.

This doesn’t mean you cannot use AI for learning or fixing some issues. AI is a fantastic tool for learning and helping find and fix issues. Use it for that, not for generating the entire extension. For sure, in the future, AI can generate very high quality code without any unnecessary lines but until then, if you want to start writing extensions, you can always ask us in the GNOME Extensions Matrix channel .

TLA+ Modeling Tips

Hacker News
muratbuffalo.blogspot.com
2025-12-17 08:05:30
Comments...
Original Article

Model minimalistically

Start from a tiny core, and always keep a working model as you extend. Your default should be omission. Add a component only when you can explain why leaving it out would not work. Most models are about a slice of behavior, not the whole system in full glory: E.g., Leader election, repair, reconfiguration. Cut entire layers and components if they do not affect that slice. Abstraction is the art of knowing what to cut . Deleting should spark joy.

Model specification, not implementation

Write declaratively. State what must hold, not how it is achieved. If your spec mirrors control flow, loops, or helper functions, you are simulating code. Cut it out. Every variable must earn its keep. Extra variables multiply the state space (model checking time) and hide bugs. Ask yourself repeatedly: can I derive this instead of storing it? For example, you do not need to maintain a WholeSet variable if you can define it as a state function of existing variables: WholeSet == provisionalItems \union nonProvisionalItems .

Review the model for illegal knowledge

Do a full read-through of your model and check what each process can really see. TLA+ makes it easy to read global state (or another process's state) that no real distributed process could ever observe atomically. This is one of the most common modeling errors. Make a dedicated pass to eliminate illegal global knowledge.

Check atomicity granularity

Push actions to be as fine-grained as correctness allows. Overly large atomic actions hide races and invalidate concurrency arguments. Fine-grained actions expose the real interleavings your protocol must tolerate.

Think in guarded commands, not procedures

Each action should express one logical step in guarded-command style . The guard should ideally define the meaning of the action. Put all enablement conditions in the guard. If the guard holds, the action may fire at any time in true event-driven style. This is why I now prefer writing TLA+ directly over PlusCal: TLA+ forces you to think in guarded-command actions, which is how distributed algorithms are meant to be designed. Yes, PlusCal is easier for developers to read, but it also nudges you toward sequential implementation-shaped thinking. And recently, with tools like Spectacle , sharing and visually exploring TLA+ specs got much easier .

Step back and ask what you forgot to model

There is no substitute for thinking hard about your system. TLA+ modeling is only there to help you think hard about your system, and cannot substitute thinking about it. Check that you incorporated all relevant aspects: failures, message reordering, repair, reconfiguration.

Write TypeOK invariants

TLA+ is not typed, so you should state types explicitly and early by writing TypeOK invariants. A good TypeOK invariant provides an executable documentation for your model. Writing this in seconds can save you many minutes of hunting runtime bugs through TLA+ counterexample logs.

Write as many invariants as you can

If a property matters, make it explicit as an invariant. Write them early. Expand them over time. Try to keep your invariants as tight as possible. Document your learnings about invariants and non-invariants. A TLA+ spec is a communication artifact. Write it for readers, not for the TLC model checker. Be explicit and boring for the sake of clarity.

Write progress properties

Safety invariants alone are not enough. Check that things eventually happen: requests complete, leaders emerge, and goals accomplished. Many "correct" models may quietly do nothing forever. Checking progress properties catch paths that stall.

Be suspicious of success

A successful TLC run proves nothing unless the model explores meaningful behavior. Low coverage or tiny state spaces usually mean the model is over-constrained or wrong. Break the spec on purpose to check that your spec is actually doing some real work, and not giving up in a vacuous/trivial way. Inject bugs on purpose. If your invariants do not fail, they are too weak. Test the spec by sabotaging it.

Optimize model checking efficiency last

Separate the model from the model checker. The spec should stand on its own. Using the cfg file, you can optimize for model checking by using appropriate configuration, constraints, bounds for counters, and symmetry terms.

You can find many examples and walkthroughs of TLA+ specifications on my blog .

There are many more in the TLA+ repo as well.

US threatens EU digital services market access

Hacker News
twitter.com
2025-12-17 08:04:02
Comments...

P: Formal Modeling and Analysis of Distributed (Event-Driven) Systems

Hacker News
github.com
2025-12-17 07:42:09
Comments...
Original Article

Formal Modeling and Analysis of Distributed (Event-Driven) Systems

NuGet GitHub license GitHub Action (CI on Windows) GitHub Action (CI on Ubuntu) GitHub Action (CI on MacOS) Tutorials

Challenge : Distributed systems are notoriously hard to get right. Programming these systems is challenging because of the need to reason about correctness in the presence of myriad possible interleaving of messages and failures. Unsurprisingly, it is common for service teams to uncover correctness bugs after deployment. Formal methods can play an important role in addressing this challenge!

P Overview: P is a state machine based programming language for formally modeling and specifying complex distributed systems. P allows programmers to model their system design as a collection of communicating state machines. P supports several backend analysis engines (based on automated reasoning techniques like model checking and symbolic execution) to check that the distributed system modeled in P satisfy the desired correctness specifications.

If you are wondering "why do formal methods at all?" or "how is AWS using P to gain confidence in correctness of their services?" , the following re:Invent 2023 talk answers this question, provides an overview of P, and its impact inside AWS: (Re:Invent 2023 Talk) Gain confidence in system correctness & resilience with Formal Methods (Finding Critical Bugs Early!!)

Impact : P is currently being used extensively inside Amazon (AWS) for analysis of complex distributed systems. For example, Amazon S3 used P to formally reason about the core distributed protocols involved in its strong consistency launch. Teams across AWS are now using P for thinking and reasoning about their systems formally. P is also being used for programming safe robotics systems in Academia. P was first used to implement and validate the USB device driver stack that ships with Microsoft Windows 8 and Windows Phone.

Experience and lessons learned : In our experience of using P inside AWS, Academia, and Microsoft. We have observed that P has helped developers in three critical ways: (1) P as a thinking tool : Writing formal specifications in P forces developers to think about their system design rigorously, and in turn helped in bridging gaps in their understanding of the system. A large fraction of the bugs can be eliminated in the process of writing specifications itself! (2) P as a bug finder : Model checking helped find corner case bugs in system design that were missed by stress and integration testing. (3) P helped boost developer velocity : After the initial overhead of creating the formal models, future updates and feature additions could be rolled out faster as these non-trivial changes are rigorously validated before implementation.

Programming concurrent, distributed systems is fun but challenging, however, a pinch of programming language design with a dash of automated reasoning can go a long way in addressing the challenge and amplify the fun!.

Let the fun begin!

You can find most of the information about the P framework on: http://p-org.github.io/P/ .

What is P? , Getting Started , Tutorials , Case Studies and related Research Publications . If you have any further questions, please feel free to create an issue , ask on discussions , or email us

P has always been a collaborative project between industry and academia (since 2013) 🥁. The P team welcomes contributions and suggestions from all of you!! 👊. See CONTRIBUTING for more information.

qjp - turn any json file into a quick TUI menu

Lobsters
github.com
2025-12-17 07:28:16
Comments...
Original Article

qjp

qjp quick demo

qjp (quick json picker) is an interactive command-line menu for filtering and selecting JSON objects or plain text lines. It provides a quick unix-pipeline friendly way to add an interactive menu to your shellscripts.

Feed it a JSON array via stdin or from a file, optionally specify which field(s) to display, and qjp will present an interactive list. Type to filter, use arrow keys to navigate, press Ctrl+Space to multi-select, press Enter to output your selection - either as complete JSON objects or just specific field values.

Table of Contents

Features

  • Interactive filtering and selection of JSON objects or plain text lines
  • Control over what gets displayed and what gets output.
  • Real-time filtering as you type
  • Multi-select support with Ctrl+Space
  • Read from stdin or directly from a file
  • Display one or multiple attributes while browsing
  • Table mode, displaying attributes vertically aligned for readability
  • Line mode. Ignore json, behave like percol
  • Optional line truncate for long content. Wraps lines otherwise.
  • Output the entire selected object(s) or a specific attribute
  • Arrays and objects output as single-line JSON

Installation

Download Pre-built Binaries

Download the binary directly for your platform from the Releases page.

Quick install scripts

# Linux (x86_64)
sudo curl -L -o /usr/local/bin/qjp "https://github.com/plainas/qjp/releases/latest/download/qjp-linux-x86_64"
sudo chmod +x /usr/local/bin/qjp

# Linux (ARM64 / aarch64)
sudo curl -L -o /usr/local/bin/qjp "https://github.com/plainas/qjp/releases/latest/download/qjp-linux-arm64"
sudo chmod +x /usr/local/bin/qjp

# Linux (ARMv7)
sudo curl -L -o /usr/local/bin/qjp "https://github.com/plainas/qjp/releases/latest/download/qjp-linux-armv7"
sudo chmod +x /usr/local/bin/qjp

# macOS (Intel)
sudo curl -L -o /usr/local/bin/qjp "https://github.com/plainas/qjp/releases/latest/download/qjp-darwin-x86_64"
sudo chmod +x /usr/local/bin/qjp


# macOS (Apple Silicon)
sudo curl -L -o /usr/local/bin/qjp "https://github.com/plainas/qjp/releases/latest/download/qjp-darwin-arm64"
sudo chmod +x /usr/local/bin/qjp

Install the manpage on your system (optional)

sudo curl -L -o /usr/local/share/man/man1/qjp.1 "https://github.com/plainas/qjp/releases/latest/download/qjp.1"
sudo mandb

Build from Source

Usage

qjp [filename] [-d display-attribute] [-o output-attribute] [-s separator] [-t] [-T] [-l] [-a]
qjp [-d display-attribute] [-o output-attribute] [-s separator] [-t] [-T] [-l] [-a] < input

Arguments

  • filename : (optional) JSON file to read (or plain text with -l ). If not provided, reads from stdin.
  • -d <attribute> : Display specific attribute(s) in list (can be used multiple times for multiple attributes)
  • -o <attribute> : Output specific attribute from selected object(s). Arrays and objects are output as single-line JSON.
  • -s <separator> : Separator for multiple display attributes (default: " - ")
  • -t : Truncate long lines instead of wrapping
  • -T : Table mode - align attributes in columns
  • -l : Line mode - treat input as plain text lines (like percol). Cannot be used with -d , -o , -s , -t , -T , or -a .
  • -a : Display all attributes - automatically discover and display all unique attributes from all objects in alphabetical order. Cannot be used with -d or -l . Particularly useful with -T for a structured overview.
  • -h, --help : Show help message

Note: Input can be provided via stdin or filename, but not both.

For detailed usage information, see the man page:

man ./qjp.1
# Or after installation:
man qjp

Keyboard Controls

  • Type : Filter the list in real-time
  • Up/Down arrows : Navigate through the list
  • Ctrl+Space : Toggle selection (multi-select mode - selected items shown with green background)
  • Enter : Confirm selection (outputs selected item(s))
  • Backspace : Delete the last character from the filter
  • Esc or Ctrl+C : Exit without selecting

Examples

Basic example below use the sample cars.json included in the source.

##############################################################
## Basic usage
##############################################################

# Read from file and display entire objects.
# Outputs entire objects one per line
qjp cars.json

# Read from file and display only car models name when selecting
qjp cars.json -d model

# Display car models and output only the ID
qjp cars.json -d model -o id

# Display multiple attributes (year, make and model) with default separator " - "
qjp cars.json -d year -d make -d model -o price

# Display multiple attributes with custom separator
qjp cars.json -d model -d year -s " | "

# Display multiple attributes in table mode (aligned columns)
qjp cars.json -d make -d model -d year -T

# Display all attributes (discovers all keys automatically)
qjp cars.json -a

# Display all attributes in table mode
# Useful for quickly inspecting the contents of a file
qjp cars.json -a -T

# Truncate long lines.
# this can be usefull while working with large objects
qjp cars.json -t

# Read from stdin (traditional pipe usage)
cat cars.json | qjp -d model

# Display car make and model and output the price
cat cars.json | qjp -d make -d model -o price

# Line mode: select from plain text lines (like percol)
ls -la | qjp -l
cat file.txt | qjp -l
ps aux | qjp -l


##############################################################
## Advanced examples
##############################################################

# Select one of Linus Torvalds repositories on github and output its number of stars
curl -s "https://api.github.com/users/torvalds/repos" | qjp -d name -d description -o stargazers_count

# A country picker that display common names and outpouts two leter country codes.
curl -s "https://www.apicountries.com/countries" | qjp -d name -o alpha2Code

# Minimal lobste.rs reased on your terminal
curl -s "https://lobste.rs/hottest.json" | qjp -d title -o url | xargs lynx

# Get the ID of a docker container by name. Useful to feed into other commands
docker ps --format json | jq -s '.' | qjp -d Names -d Status -o ID

# a quick way to find and install npm packages
npm search --json typescript | qjp -d name -d description -o name | xargs npm install

# Pick a cryptocurrency and retrieve its details from coingecko
curl -s "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=50" | qjp -d name -d symbol -d current_price | jq .

Development

Publishing a new release

To create a new release, create a tag starting with v

git tag -a v0.1.0 -m "Release v0.1.0"
git push origin v0.1.0

The GoReleaser workflow will automatically build binaries for all supported platforms and create a GitHub release.

Cross-compilation

To build for a specific platform locally:

# Linux AMD64
GOOS=linux GOARCH=amd64 go build -o qjp-linux-amd64

# macOS ARM64 (Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o qjp-darwin-arm64

# Windows AMD64
GOOS=windows GOARCH=amd64 go build -o qjp-windows-amd64.exe

TODO

  • Support jq syntax
  • Add support for jsonlines input
  • Add a classifier to automatically detect input format
  • output as json array
  • add option to output single values as json encoded
  • write a tutorial
  • record a more complete screencast

License

MIT License - see LICENSE file for details.

Subsets (YC S23) is hiring engineers in Copenhagen, Denmark

Hacker News
www.workatastartup.com
2025-12-17 07:00:16
Comments...
Original Article

Check out other YC startups on Work at a Startup below.

Sign up to see more ›

Opus 1.6 Released

Lobsters
opus-codec.org
2025-12-17 06:43:21
Comments...

Calling all arguments

Lobsters
xania.org
2025-12-17 06:10:10
Comments...
Original Article

Written by me, proof-read by an LLM.
Details at end.

Today we’re looking at calling conventions 1 - which aren’t purely optimisation related but are important to understand. The calling convention is part of the ABI (Application Binary Interface), and varies from architecture to architecture and even OS to OS. Today I’ll concentrate on the System V ABI for x86 on Linux, as (to me) it’s the most sane ABI.

Before we go on: I’d be remiss if I didn’t point out that I can never remember which register has what it in, and for years I had a Post It note on my monitor with a hand-written crib sheet of the ABI. While on holiday I had an idea: Why not put the ABI on a mug! I created these ABI mugs and you can get your own one - and support Compiler Explorer - at the Compiler Explorer shop .

Some Compiler Explorer mugs with ABI information on them
The Compiler Explorer ABI mug: Get yours at the CE Shop!

We’ve already touched on calling conventions as I’ve commented the assembly in previous days, but concretely, for x86 Linux, the first couple of parameters go in rdi and rsi 2 . This makes sense for discrete integer types, and even pointers. What about structures? Let’s compare two functions:

With ArgType set to long it might surprise you that the body of those two functions are identical! Both are just lea rax, [rdi+rsi] : We expect the separate arguments to be in rdi and rsi , but passing that larger structure by value also got placed in rdi and rsi . Neat!

If you explore by changing the ArgType you’ll see that the compiler has to do more work if we don’t (conveniently) use long s here. For example, changing to int changes the separate argument version to lea eax... to reflect the 32-bit return value, but the body of the structure version becomes:

; structure is _packed_ into rdi as "y<<32 | x"
  mov rax, rdi      ; rax = args.y<<32 | args.x
  shr rax, 32       ; rax >>= 32; rax is now 'y'
  add eax, edi      ; y += x;
  ret

It’s a little tricky to follow as the compiler is cunningly switching between the 64-bit r prefixed register names and the 32-bit e versions, but you can see that, for the cost of a couple more instructions we still passed the structure pretty efficiently, and in a single register.

It gets more interesting when we pass lots of arguments 3 . Even on System V ABI, only the first 6 parameters are passed in registers. After that, it spills to the stack. Let’s update our example to pass many arguments to show this:

In this case we can see the separate args version adding all the registers, and then having to get some off the stack: add rax, QWORD PTR [rsp+8] and so on. On the structure side, the whole structure 5 is copied to the stack, which seems bad 4 .

However! Changing ArgType to char and you’ll see an interesting difference. The separate args version is similar, though it can’t use lea any more, and has to sign-extend all the values its getting from its registers. The struct args version has no stack spillage: our entire StructArgs structure fits into one register! The compiler has a bit of a time shifting it around to extract each char , but it’s not having to spill to the stack at least. In my testing, different compilers used different tricks, so play around with the ArgType and compiler (e.g. clang) and get a sense of what it can do 6 .

So, all this is pretty abstract: why is this important? Sometimes knowing the ABI, and how the compiler can optimise around it can inform your design. There was some debate about the design of std::string_view and std::optional and their usefulness 8 : these are types that are convenient to pass by value , and so their footprint in registers is important 7 .

Overall, knowing the calling convention helps you make smart decisions about layout and parameter passing that give the compiler the best shot at generating efficient code.

See the video that accompanies this post.


This post is day 16 of Advent of Compiler Optimisations 2025 , a 25-day series exploring how compilers transform our code.

This post was written by a human ( Matt Godbolt ) and reviewed and proof-read by LLMs and humans.

Support Compiler Explorer on Patreon or GitHub , or by buying CE products in the Compiler Explorer Shop .

Posted at 06:00:00 CST on 16 th December 2025.

This is Europe's secret weapon against Trump: it could burst his AI bubble | Johnny Ryan

Guardian
www.theguardian.com
2025-12-17 05:00:25
Growth in the US economy – and the president’s political survival – rest on AI. The EU must use its leverage and stand up to him The unthinkable has happened. The US is Europe’s adversary. The stark, profound betrayal contained in the Trump administration’s national security strategy should stop an...
Original Article

T he unthinkable has happened. The US is Europe’s adversary. The stark, profound betrayal contained in the Trump administration’s national security strategy should stop any further denial and dithering in Europe’s capitals. Cultivating “resistance Europe’s current trajectory in European nations” is now Washington’s stated policy.

But contained within this calamity is the gift of clarity. Europe will fight or it will perish. The good news is that Europe holds strong cards.

The US’s bet on AI is now so gigantic that every Maga voter’s pension is bound to the bubble’s precarious survival. AI investment now rivals consumer spending as the primary creator of American economic growth. It accounted for virtually all (92%) GDP growth in the first half of this year. Without it, US GDP grew only 0.1% . Despite Donald Trump’s posturing, he is on shaky economic ground.

Trump’s political coalition is shaky, too. In July and again this month, he has been unable to force Senate Republicans to pass his AI moratorium bill, which would have prevented states from drafting their own AI laws. The Steve Bannon wing of Maga fears that AI will displace workers en masse, and is appalled by what children are exposed to on digital platforms. Maga voters particularly mistrust big tech’s political power. Tech is a dangerous topic for Trump.

Ursula von der Leyen, the president of the European Commission, has two cards to play that might pop the AI bubble. If she does so, Trump’s presidency will be thrown into crisis.

First, Dutch company ASML commands a global monopoly on the microchip-etching machines that use light to carve patterns on silicon. These machines are essential for Nvidia, the AI microchip giant that is now the world’s most valuable company. ASML is one of Europe’s most valuable companies, and European banks and private equity are also invested in AI. Withholding these silicon-etching machines would be difficult for Europe, and extremely painful for the Dutch economy. But it would be far more painful for Trump.

The US’s feverish investment in AI and the datacentres it relies on will hit a wall if European export controls slow or stop exports to the US – and to Taiwan, where Nvidia produces its most advanced chips. Via this lever, Europe has the means to decide whether and by how much the US economy expands or contracts.

Second, and much easier for Europe, is the enforcement of the EU’s long-neglected data rules against big US tech companies. Confidential corporate documents made public in US litigation show how vulnerable companies such as Google can be to the enforcement of basic data rules. Meanwhile, Meta has been unable to tell a US court what its internal systems do with your data, or who can access it, or for what purpose.

This data free-for-all lets big tech companies train their AI models on masses of everyone’s data, but it is illegal in Europe, where companies are required to carefully control and account for how they use personal data. All Brussels has to do is crack down on Ireland, which for years has been a wild west of lax data enforcement , and the repercussions will be felt far beyond.

If the EU had the gumption to apply this pressure, these US tech companies would have to rebuild their technologies from the ground up to handle data correctly. They would also have to tell investors that their AI tools are barred from accessing Europe’s valuable market until they comply. The AI bubble would be unlikely to survive this double shock.

Maga voters did not vote to lose their liberties and constitutional rights, and an increasingly authoritarian Trump who cannot deliver economic stability because of his closeness to a reviled tech industry is likely to be deeply unpopular in the 2026 midterm elections.

The balance of risk now demands that European leaders cripple Trump. They have learned from a year of abject cowering before Trump that such behaviour only makes it easy for him to push them over. The reasons for caution are disappearing. The extreme reaction of Maga leaders to the relatively minor €120m fine the EC recently imposed on X shows that pulling punches will not placate them. Trump’s “ 28-point plan ” for Ukraine dispelled any illusion that European concessions would secure a return to US military commitment.

With its democracy now explicitly under threat, Europe must join India, Brazil and China in standing up to Trump.

Brazil’s president Luiz Inácio Lula da Silva is an example of how to do so. He has been dignified and resolute in the face of extraordinary bullying from Trump. In a single month, in September, he proclaimed in an open letter to Trump that his country’s democracy and sovereignty are non-negotiable, countered Trump’s tariffs with its own and passed a new law forcing digital platforms to protect children in Brazil from sexual harassment and other online harms.

Then he rhetorically mugged Trump in a UN general assembly speech just before Trump’s turn to speak. As a result of Lula’s refusal to be cowed, Trump softened his tone immediately . Lower tariffs are now expected after negotiations between the two leaders.

Trump said earlier in December that he thinks Europe’s leaders are weak. He does not believe they will defend Europeans’ liberties and their hard-won democracy against him. So far, the response from European leaders is proving him correct. But what Trump does not yet understand is that von der Leyen holds the US economy and his presidency in her hands. She must have the courage to go entirely beyond any prior norms of her behaviour. In other words, if she grabs Trump where it hurts, Europe will win this fight.

  • Johnny Ryan is director of Enforce, a unit of the Irish Council for Civil Liberties

FTX insider Caroline Ellison has been moved out of prison

Hacker News
www.businessinsider.com
2025-12-17 04:48:24
Comments...
Original Article

Caroline Ellison.

Caroline Ellison has been transferred out of federal prison. AP Photo/Eduardo Munoz Alvarez
  • Caroline Ellison has been moved from federal prison to community confinement.
  • That means the former Alameda Research CEO is either in home confinement or a halfway house.
  • Ellison served about 11 months of her two-year prison sentence.

Caroline Ellison , the former cryptocurrency executive and ex-girlfriend of Sam Bankman-Fried , has been quietly moved out of federal lockup after serving roughly 11 months of her two-year prison sentence, Business Insider has learned.

Ellison, 31, was transferred on October 16 from the Danbury Federal Correctional Institution in Connecticut to what's known as community confinement, a Federal Bureau of Prisons spokesperson said.

That means Ellison, the former CEO of Bankman-Fried's Alameda Research cryptocurrency hedge fund, remains in federal custody but is now either in home confinement or a halfway house, BOP spokesperson Randilee Giamusso told Business Insider.

"For privacy, safety, and security reasons, we do not discuss the conditions of confinement for any individual, including reasons for transfers or release plans, nor do we specify an individual's specific location while in community confinement," Giamusso said.

Online prison records list Ellison's projected release date as February 20, 2026 — nearly nine months early. Her attorneys declined to comment for this story.

Ellison reported to the low-security Danbury prison in early November 2024 to serve a two-year sentence she received for her role in the massive multibillion-dollar fraud scheme that led to the collapse of Bankman-Fried's business empire.

She had pleaded guilty to conspiring with Bankman-Fried — the founder of the FTX crypto exchange and its sister company, Alameda Research — in the $11 billion fraud scheme.

Ellison served as the star witness in Bankman-Fried's 2023 criminal trial , testifying that the pair used Alameda to invest billions of dollars' worth of assets secretly siphoned from FTX customers.

At Ellison's sentencing hearing, US District Judge Lewis Kaplan praised her "substantial" cooperation in the prosecution of Bankman-Fried, but said the seriousness of the case still required prison time.

Her lawyers had asked that the judge not impose any prison time, but Kaplan rejected what he called a "literal get-out-of-jail-free card."

Before she was sentenced, Ellison, holding back tears, apologized and expressed regret for her participation in the fraud scheme.

"On some level, my brain doesn't even comprehend all the people I harmed," Ellison told the court. "That doesn't mean I don't try."

Bankman-Fried was sentenced by Kaplan to 25 years in prison after a jury found him guilty of all seven counts of fraud and conspiracy.

The FTX founder and former CEO remains behind bars at a low-security federal prison in San Pedro, California, as he appeals his conviction and sentence .

Bankman-Fried's lawyers have argued that he should get a new trial after prosecutors unfairly previewed his testimony.

Read next

Minimum Viable Benchmark (for evaluating LLMs)

Lobsters
blog.nilenso.com
2025-12-17 04:38:43
Comments...
Original Article

A few months ago, I was co-facilitating a “Birds of a Feather” session on keeping up with AI progress. This was a group of engineering leaders and ICs.

A big talking point was that popular public benchmarks are insufficient for determining if an AI model is a good fit for their product.

Collage from the Birds of a Feather session showing co-facilitator Lavanya Tekumala, developers discussing benchmarks and AI-assisted coding, and a whiteboard featuring the word 'benchmark' three times
clockwise: (1) My co-facilitator Lavanya Tekumala. (2) Developers talking about benchmarks and AI-assisted coding. (3) The whiteboard from the session which featured the word "benchmark" three times.

I want to sharpen this observation a bit more.

What are benchmarks useful for?

I’ve seen benchmarks serve a whole range of purposes.

  • Benchmarks as decision-making tools : You look at existing benchmarks to figure out whether to use model A or model B.
  • Benchmarks as regression markers : Like unit tests, they tell you if your updated AI model or system isn’t doing worse than before. This is especially useful in cost-optimisation exercises.
  • Benchmarks as improvement indicators : If you see benchmark go up, you can tell that your change to the model or system is improving the outcome.
  • Benchmarks as product behaviour feedback : A more subtle use—with the right analysis of trajectories, benchmarks can tell you about the strengths and weaknesses of your model across categories of tasks you are interested in.
  • Benchmarks as research agenda setters : When a new benchmark is published, AI labs start hill-climbing on it—publishing benchmarks is a great way to influence what AI is good at.
  • Benchmarks as RL environments : This is an emerging use case. Reinforcement Learning with Verifiable Rewards effectively works with a setup that doesn’t look all that different from a benchmark.
  • Benchmarks as forecasting anchors : You can use benchmarks to get a sense of how AI capabilities are progressing over time. METR has made good use of this.

If a benchmark is not helping you with any of the above, your benchmark is useless. Many useless benchmarks unfortunately exist.

Benchmark traps

Here’s the Artificial Analysis Intelligence index, which aggregates all sorts of AI benchmarks.

And here’s the most popular benchmark for testing coding ability.

These charts in isolation give the impression that AI models are pretty interchangeable and that whenever a new model comes in, you can reap the fruits of the wonderful frontier lab training pipelines. All you need to do is to switch your coding model to whatever the new hotness is. Right?

No.

The issue with benchmarks is that they are lossy. They condense multidimensional characteristics into a single number 1 . Your business case may not look like whatever your number represents.

Let’s take an example. You’re working on an AI agent that operates in the legal domain. A profoundly unserious approach would be to look at which model is doing well across standard benchmarks (like the intelligence index above) and pick that. If we put a couple of extra brain cells to work, we might look at an independent benchmark score for the most popular legal benchmark. Right now this is LegalBench.

Great, so it’s still the state-of-the-art Gemini 3 Pro, isn’t it? It’s clearly #1 on the benchmark 2 .

But look at this—there’s a CaseLaw (v2) benchmark as well.

No Gemini 3 Pro in sight. Have they forgotten to bench our frontier Gemini model here? Actually no.

Gemini 3 Pro is poor enough at this benchmark that it’s nowhere near the top of the leaderboard. In fact, it ranks #39 and is worse than the previous-generation Gemini 2.5 Flash!

Both of these are measuring different things in the legal domain, with CaseLaw appearing more like real-world legal work, and LegalBench being more like an academic exam. It’s quite possible that Gemini can be good at some parts of some domains and poor at other parts of the same domain. Or maybe the CaseLaw evaluation has some unaddressed issues (after all, there seem to be a lot of surprising results in the leaderboard). Or that Gemini hates Canadians.

This all points to one thing—don’t base your decision off benchmark scores. Instead, look at the benchmark contents and methodology, figure out how closely it aligns with what tasks you are handing off to the AI and most importantly, make your own internal benchmark , with metrics aligned to your business case 3 .

Another reason to have internal benchmarks. Not all new models may be better than what came before for your use case.

Minimum viable benchmark

Without getting into the weeds of categorisations, I’d note that internal benchmarks are not all that different from what all the hip and cool new AI Engineering teams like to call evals .

They are not structurally different from public benchmarks. You have your dataset of tasks. You (ideally) have your ground truth for these tasks. You measure your AI system against these tasks and get scores. Unfortunately, building a public benchmark is hard work—you have to collect a lot of data to get signal 4 , ensure the environments are reproducible and your metrics trustworthy. This ugh field has pushed teams away from building evals. Well, at least until it’s too late, when you suddenly have everyone scrambling to do the grunt work of collecting annotated high-quality data when the house is burning.

I’d like to propose an alternate view—your internal benchmarks don’t need to be as sophisticated as the public benchmarks. They only have to be a minimum viable benchmark .

A minimum viable benchmark is not concerned with being an arena for competing AI systems—it is a vehicle for figuring out whether you are building the right product and that the product works well.

You don’t need to have an intelligent-sounding metric or your LLM eval SaaS vendor figured out in order to get started. You only need to collect your data and annotate it. You can get started and make a lot of progress in a couple of hours, armed with only a spreadsheet and your product and engineering teams in one room.

In your sheet, ensure you have your inputs to your AI system. Add the outputs after a few runs in the system for the tasks you need 5 . Add free-form commentary in the last column about how it did. Don’t optimise anything yet. Don’t add any “metrics” yet.

After this exercise, a few things happen:

  • You realise what your task is actually like and what it might involve.
  • You realise whether the AI works at all for your task.
  • You realise what it feels like to be a user of your system and get a better sense of where AI is actually helping. This is input for the product team.
  • You realise what actually needs to be measured for your benchmark metrics. It’s never the vague, pointless metrics that came with the eval framework you were looking at.
  • The valuable metrics inferred from this exercise are often useful product metrics!
  • You catch the biggest blind spots of the AI system very early on. Gathering large datasets is needed only when you are trying to catch small effects . Early on, most of observed effects on any intervention will be quite large!
  • Most importantly, you have overcome the Ugh Field! This exercise is often fun.

This minimal viable benchmark would have already proven its usefulness early on. Everyone in your team will continue to build on top of this and rely on it when, inevitably, you have to avoid regressions, evaluate a new feature or model or optimise costs. Over time, your minimal viable benchmark can grow into a useful, strong benchmark that forms the backbone of your AI project.

How we go from a minimal viable benchmark to a maximally useful benchmark would perhaps need its own article. But to give you a taste, ensure you have these properties:

  • It’s easy to look at the data and your cross-functional team is involved in reviewing the data regularly.
  • What you are measuring maps to product outcomes—this may not be the case for public benchmarks.
  • There are enough samples to actually give you a sense of whether your system has actually improved.
  • The tasks have a difficulty ramp-up to actually capture improvements to models and systems. If most of your tasks have the same difficulty, and a newly released AI model gains the ability to do that task, your benchmark would get saturated overnight and cease to capture further improvements.
  • The metrics are measured either deterministically or with an unbiased estimator 6 .

Anyway,

  • Don’t trust public benchmark numbers without seeing if the methodology and numbers map to your product outcomes.
  • Build your own minimal viable benchmark, where what you are measuring maps to your product’s quality.
  • It’s not that hard to start with, and it’s really worth it.

A Guide to Magnetizing N48 Magnets in Ansys Maxwell

Hacker News
blog.ozeninc.com
2025-12-17 03:55:59
Comments...
Original Article

In this blog, we'll walk through a complete workflow in Ansys Maxwell to simulate the magnetization of a specific permanent magnet, the N48SH, using only its manufacturer datasheet. We will then validate our results against Maxwell’s built-in material library to demonstrate the accuracy of this powerful technique.

1. The Physics of Magnetization & Our Simulation Model


Before diving into the simulation, let's briefly review the underlying physics. The behavior of a magnetic material is described by its B-H curve, or hysteresis loop. When we first magnetize a material, it follows an "Initial Magnetizing" path from (0,0) up to saturation. Once the external magnetizing field is removed, the magnet's flux density "recoils" to a point in the second quadrant, known as its operating point. This second quadrant, the demagnetization curve, is what defines the magnet's performance in an application.

Hysteresis loop of a typical NdFeB magnet, showing the initial magnetization curve and the second-quadrant demagnetization region.

A permanent magnet in open air will generate a "demagnetizing" field within itself, where the magnetic field (H) opposes the direction of magnetization. The intersection of this self-demagnetizing field and the material's B-H curve determines the magnet's operating point.

Example operating point for an N48 magnet on its demagnetization curve (left). Vector plot of the H-field showing the external field and the internal demagnetizing field of a permanent magnet (right).

To simulate this process, we've created a simple magnetizer model in Ansys Maxwell. It consists of two current-carrying coils and two steel cores that work together to generate and direct a strong, uniform magnetic field (H-field) in the space between them. We will place our unmagnetized N48SH material, a simple rectangular block, in this region to be magnetized.

Simulation showing the current density (J) in the coils and the resulting magnetic field (H) generated between them.

Vector plot showing the magnetic field (H) in and around the entire magnetizer assembly.

2. Creating a Custom Initial Magnetizing Curve

The Ansys Learning Hub features an excellent tutorial on magnetic latching that demonstrates the magnetization of a generic Neodymium magnet.

In this blog, we want to take it a step further and simulate a specific material, the N48SH , using its datasheet, and then validate our results by comparing its final operating point to that of Maxwell's built-in N48 material.

Our first step is to get the material data into Maxwell. The N48SH datasheet provides its demagnetization curve graphically. We can use Maxwell’s powerful SheetScan utility to digitize this curve.

N48SH datasheet from Arnold Magnetic Technologies (left). Using the SheetScan tool in Ansys Maxwell to digitize the B-H curve from the datasheet image (right).

(We have a detailed tutorial on how to use the SheetScan tool, which you can find at this link: Ansys Maxwell: SheetScan - Import Material Characteristic Curves )

Next, we need an initial magnetization curve. The Ansys Learning Hub magnetization workshop files provide a "virgin" (Initial) BH curve for a generic NdFeB magnet. Our goal is to modify this generic curve so that it smoothly connects to the N48SH demagnetization curve we just extracted.

Generic NdFeB virgin BH curve provided in the Ansys Maxwell training materials.

By plotting our extracted N48SH curve and extrapolating it into the first quadrant, we can see how the generic curve needs to be adjusted to line up correctly.


Comparison of the generic initial BH curve (green) and the extrapolated N48SH datasheet curve (blue). Curve after extrapolation is on the right.

Using the BH curve smoother tool, we can modify the generic initial curve (green) to align with the N48SH datasheet curve (blue).

New initial BH curve (green), after being modified to align with the N48SH datasheet curve (blue).

With our modified curve ready, we create a new material in Maxwell called "N48_Unmagnetized" and import our custom initial BH curve.

Defining the new material in Maxwell with the custom nonlinear BH curve.

Finally, and this is a crucial step, we must tell Maxwell that we intend to compute the final magnetized state of our permanent magnet object. This is done by right-clicking on Excitations , selecting Set Magnetization Computation , and checking "Compute magnetized operating points" for our PM object.

Enabling the "Compute magnetized operating points" option for the permanent magnet.

3. Running the Simulations and Evaluating Results

Now we're ready to run the simulation. This is a two-step process using linked magnetostatic analyses.

Step 1: The Magnetizing Event

We run the first simulation with the current applied to the coils. Maxwell solves for the magnetic field and determines the operating point of the PM as it's being driven up the initial magnetization curve by the strong external H-field.

The H-field produced by the coils during the magnetizing event.

Plot showing the operating point during the magnetization event, landing on the virgin BH curve.

Step 2: Simulate The Final Magnetized State

To find the final operating point after the magnetizer is turned off, we create a copy of the first design. In this new design, we do two things:

  1. Set the current in the magnetizing coils to zero.

  2. Assign a Permanent Magnet Field to the PM object. This feature links the second simulation to the first, using the computed magnetized state from the first analysis as the source for the permanent magnet's field in the second.

Setting up the Permanent Magnet Field in the second analysis, linking it to the result of the first magnetizing event.

After running this second analysis, we can plot the complete history. The graph below shows the magnet's operating point starting at (0,0), traveling up the green initial magnetization curve during the magnetizing event, and then following a recoil line down to its new, stable operating point in the second quadrant. We've also plotted the BH curve of the N48 material in yellow, showing how the magnet's final state lies on the expected demagnetization path.

Plot showing the full magnetization history: the initial curve (green), the peak point during magnetization, the recoil path, and the final newly magnetized operating point.

Step 3: Validation

For our final step, we'll create a third version of the model, again with zero current. This time, instead of using our custom material, we'll assign the PM the material properties of the built-in N48SH material from Maxwell's library.

Assigning the built-in N48SH material properties for the validation simulation.

By running this third simulation, we can directly compare the operating point of our custom-magnetized PM with the operating point of a standard N48 magnet. As the final plot shows, the two points are nearly identical, validating that our workflow has successfully and accurately simulated the magnetization of an N48SH magnet from its datasheet.

Final comparison plot showing the operating point of our newly magnetized PM (blue circle) is almost identical to the operating point of the built-in N48 material (red dot), validating the accuracy of the workflow.

4. Conclusions

This workflow demonstrates a powerful capability within Ansys Maxwell. By starting with a graphical demagnetization curve from a manufacturer's datasheet, you can create a custom initial BH curve to accurately simulate the entire magnetization process. The two-step linked analysis allows you to first compute the magnetization and then determine the final, stable operating point of the newly created permanent magnet.

The close agreement between our simulated magnet and Maxwell's built-in N48 material validates this approach. This gives engineers the confidence to apply the same technique to virtually any permanent magnet material, enabling high-fidelity simulation and robust design even when a complete set of material data isn't readily available.

Adventures in the land of Language Servers

Lobsters
speakerdeck.com
2025-12-17 03:35:27
Comments...
Original Article

Have you ever wondered how your editors and IDEs are able to support so many programming languages? Perhaps you've been thinking about designing your own language and wanted to know how you can give it editor support?

This talk is for you - I've spent over a year building a small language and integrating it with code editors, and I'd like to share some of the challenges I've faced, as well as lessons I've learned in that time.

I'll also show how easy it is to build a new Language Server project in Scala 3 thanks to the Langoustine library.

Avatar for Jakub Kozłowski

Transcript

  1. Storytime - meet Jane. 👩💻

  2. Jane is tasked with building a language... • A small

    DSL meant to be used in an existing application • The application is JVM-based (Scala) • the compiler also needs to work on the JVM • 2-3 weeks later, the compiler is done and embedded in the application • Jane's life is good! • until...

  3. 😳 Jane starts getting users And they want editor support

  4. 😭 More users And this time they want VS Code

  5. Jane decides to shell out 🐚 Client-server architecture • The

    editor extension (language frontend) will start a server in a separate process • A compilation server (language backend) will run on the JVM ☕ • The editor extension will send RPCs to the server ☎ • When the editor is closed, the extension will kill the server process 💀

  6. How it'll all work • The editor extension (language frontend)

    will: • Listen to user events 👂 (hover, clicks, keyboard shortcuts...) • Ask the server for information 🙋 (completions at position...) • Provide parameters 🧱 (cursor position, fi le contents...) • Apply actions and present results 🏋 (complete statement, go to de fi nition...) Client responsibilities

  7. Jane needs an API for the communication • Jane wants

    to call it "Language Server Protocol", but a quick Google search tells her it's taken... • She decides to call it "Language Backend Protocol" ✅ • It'll use HTTP over local TCP ✅ trait LanguageBackend { def definition( cursor: Position, file: Path ): Location def rename( position: Position, file: Path, newName: String ): List[TextEdit] //... }

  8. 🤔 Jane gets a DM Meet Trish

  9. Server capabilities A means for a server to describe what

    it can do • A new method in the protocol: initialize • Called by the client after server launches • The server responds with a list of supported methods • Unsupported features aren't advertised by the client ✅ • Servers and clients can add features at their own pace ✅ • Only features that make sense have to be implemented ✅

  10. Jane and Trish get to work... • Jane's server declares

    its capabilities • Trish's new methods are added to the protocol • Trish implements a language backend • The extensions are updated to hide unsupported features • The extensions can be con fi gured to launch di ff erent backends • Jane's life is good • until...

  11. 😱 User complaint Some actions are visibly slow...

  12. Users can't see any feedback In the middle of an

    action • Some actions are inherently slow ⏳ • Sometimes you just need to tell the user to wait a little more, or ask them for con fi rmation • Only the client can initiate calls ↪ • The protocol doesn't give the server the ability to respond with intermediate results ↩

  13. Updates to the initialize request • Not every client can

    handle features like noti fi cations • Clients will advertise their capabilities in the initialize request • Servers will adjust behavior based on client capabilities trait LanguageBackend { def initialize( clientCapabilities: ClientCapabilities ): ServerCapabilities //... }

  14. Updates to the initialize request • Not every client can

    handle features like noti fi cations • Clients will advertise their capabilities in the initialize request • Servers will adjust behavior based on client capabilities trait LanguageBackend { def initialize( clientCapabilities: ClientCapabilities ): ServerCapabilities //... }

  15. Jane gets to work • The editor extensions are updated

    to advertise their capabilities • The server and extensions add support for the server -> client requests • Language backends can now provide estimations, noti fi cations, logs ✅ • Jane's life is good • until...

  16. 💀 User complaint The editors are often breaking...

  17. Users can't do anything without saving the file Jane immediately

    knows the cause of the issue • The protocol identi fi es fi les by their disk path • Editors don't save fi les on each keystroke (disk I/O is slow) • The fi les aren't always up to date with the editor state ❌ • The protocol needs to account for unsaved fi les 💾 trait LanguageBackend { def definition( cursor: Position, file: Path ): Location def rename( position: Position, file: Path, newName: String ): List[TextEdit] //... }

  18. Syncing text New methods in the protocol • New methods:

    onChanged/onSaved/onClosed • When the fi le changes, editor extension sends updates • These can be patches (if the server is capable) or entire fi les • The server will keep these in memory • When the fi le is closed/saved, the extension informs the server • The server can delete these from memory

  19. 🥰 Giving back Why keep this to ourselves?

  20. Jane will return (Not really, this is the end)

  21. 🔄 LSP - a summary

  22. No LSP: M * N integrations Source: https://code.visualstudio.com/api/language-extensions/language-server-extension-guide

  23. Yes LSP: M + N integrations Source: https://code.visualstudio.com/api/language-extensions/language-server-extension-guide

  24. Example: go to definition https://github.com/kubukoz/badlang

  25. Go to definition in LSP

  26. Go to definition in LSP

  27. Go to definition in LSP

  28. Go to definition in LSP

  29. Go to definition in LSP

  30. 🤺 Challenges I've faced

  31. 🔎 Parsing

  32. Parsing Making text structured

  33. Parsing, more honest Ranges included

  34. Parsing test harness Derive tests from directory structure

  35. Parsing test harness Derive tests from directory structure

  36. More ideas for graceful parsing "we want parsing to always

    succeed at producing some kind of structured result. The result can contain error nodes inside it, but the error nodes don't have to replace the entire result"
 
 "(...) every string matches a rule, by adding rules for erroneous inputs" https://duriansoftware.com/joe/constructing-human-grade-parsers

  37. 🖨 Formatting

  38. Formatting Tests - you're gonna need these https://github.com/kubukoz/smithy-playground (FormattingTests.scala)

  39. 🔬 Testing

  40. Testing The pyramid still applies

  41. 🐞 Debugging

  42. Debugging

  43. 📚 Library choice

Why many Asian megacities are miserable places

Hacker News
www.economist.com
2025-12-17 03:03:32
Comments...

Tesla Robotaxis in Austin Crash 12.5x More Frequently Than Humans

Hacker News
electrek.co
2025-12-17 02:52:22
Comments...
Original Article
Tesla Robotaxi hero

Tesla has reported yet another crash involving its Robotaxi fleet in Austin to the NHTSA. The new data keeps the program’s accident rate alarmingly high compared to human drivers, even as the company prepares to remove human safety supervisors from the vehicles .

As we have been tracking in our previous coverage of the Robotaxi pilot in Austin, Tesla is required to report crashes involving its automated driving systems (ADS) to the NHTSA under a Standing General Order.

For months, we’ve seen these reports trickle in from Tesla’s small pilot fleet in Texas. In November, we reported that the fleet had reached 7 total crashes as of September.

Now, a new report filed by Tesla reveals an 8th crash occurred in October 2025.

According to the filing, the incident took place on October [Day Redacted], 2025, in Austin. The valid report (Report ID: 13781-11986) lists the “Highest Injury Severity Alleged” as “No Injured Reported,” but details are scarce because, as is typical for Tesla, the narrative description of the crash has been redacted to hide proprietary information.

We have been highlighting how Tesla often abuses NHTSA’s capability to redact much of the information in the crash reports, especially the ‘Narrative’ section, which explains precisely what happened in the incident.

It’s possible that Tesla’s Robotaxis are not responsible for some of these crashes, but we wouldn’t know because Tesla redacts most information.

In this new filing for the accident that happened in October, Tesla went even further as it even refrains from answering some of the sections. Instead, it says “see the narrative,” which again is redacted.

Here’s the updated list of Tesla Robotaxi crashes:

Report ID Incident Date City State Crash With Highest Injury Severity Alleged
13781-11986 OCT-2025 Austin TX Other, see Narrative No Injured Reported
13781-11787 SEP-2025 Austin TX Animal No Injured Reported
13781-11786 SEP-2025 Austin TX Non-Motorist: Cyclist Property Damage. No Injured Reported
13781-11784 SEP-2025 Austin TX Passenger Car Property Damage. No Injured Reported
13781-11687 SEP-2025 Austin TX Other Fixed Object Property Damage. No Injured Reported
13781-11507 JUL-2025 Austin TX SUV Property Damage. No Injured Reported
13781-11459 JUL-2025 Austin TX Other Fixed Object Minor W/O Hospitalization
13781-11375 JUL-2025 Austin TX SUV Property Damage. No Injured Reported

We do know that the crash involved “Other” as the conflict partner, and the vehicle was “Proceeding Straight” at the time.

Tesla Robotaxi Crash Rate

While a few fender benders might not seem like headline news, it becomes significant when you look at the math.

Last month, Tesla confirmed the fleet had traveled roughly 250,000 miles. With 7 reported crashes at the time, Tesla’s Robotaxi was crashing roughly once every 40,000 miles (extrapolating from the previously disclosed Robotaxi mileage).

For comparison, the average human driver in the US crashes about once every 500,000 miles.

This means Tesla’s “autonomous” vehicle, which is supposed to be the future of safety, is crashing 10x more often than a human driver.

While Tesla’s Robotaxi fleet reportedly increased in November, with the number of cars spotted going up to 29, there’s no evidence that the Robotaxi mileage increased. In fact, the utilization rate indicates Tesla is running only a few vehicles at a time – meaning that mileage might have actually gone down.

And that is not even the scariest part.

The Supervisor Paradox

The most critical detail that gets lost in the noise is that these crashes are happening with a human safety supervisor in the driver’s seat (for highway trips) or passenger seat, with a finger on a kill switch.

These employees are trained to intervene and take control of the vehicle if the software makes a mistake.

If the car is crashing this frequently with a human babysitter trying to prevent accidents, imagine what the crash rate would be without them.

Yet, that is exactly what Tesla is doing.

Elon Musk recently claimed that Tesla would remove safety monitors from the Robotaxi fleet in Austin within “three weeks.”

Yesterday, we reported that a Tesla Robotaxi was spotted for the first time without anyone in the front seat s, and Musk confirmed that Tesla started testing without a supervisor.

Electrek’s Take

This is becoming hard to watch.

We have Waymo operating fully driverless commercial services in multiple cities with over 100 million miles of data showing they are safer than humans. They are not without their issues, but they are at least sharing data that is encouraging, including not redacting the NTHSA crash reporting.

Meanwhile, Tesla is struggling to keep a small test fleet in Austin from hitting things, even with professional safety drivers on board.

Removing the safety supervisors when your crash rate is already orders of magnitude worse than the average human seems reckless. It feels like another case of prioritizing the “optics” of autonomy over the actual safety required to deploy it.

If Tesla pulls the supervisors while the data looks like this, it’s no longer a pilot program. It’s a gamble. And it’s not just gambling on its stock price, it’s gambling with everyone’s safety.

Add Electrek as a preferred source on Google Add Electrek as a preferred source on Google

FTC: We use income earning auto affiliate links. More.

Yearn Finance suffers fourth exploit only weeks after third

Web3 Is Going Great
web3isgoinggreat.com
2025-12-17 02:02:13
Only weeks after losing $6.6 million to an infinite mint exploit, a Yearn Finance smart contract has again been exploited, allowing an attacker to make off with around 103 ETH (~$300,000). The affected contract is a legacy contract that was part of the Yearn v1 project (once known as iearn)...
Original Article

Only weeks after losing $6.6 million to an infinite mint exploit , a Yearn Finance smart contract has again been exploited, allowing an attacker to make off with around 103 ETH (~$300,000). The affected contract is a legacy contract that was part of the Yearn v1 project (once known as iearn). The attacker used a flash loan to manipulate the price of tokens in the vault, allowing them to withdraw the iearn assets, which they then swapped for ETH.

This is Yearn's fourth hack, following the $6.6 million theft in November, an $11 million exploit in 2023 , and an $11 million exploit in 2021 . Yearn also lost around $1.4 million in 2023 in connection to the Euler Finance attack .

Locked out: How a gift card purchase destroyed an Apple account

Hacker News
appleinsider.com
2025-12-17 02:01:38
Comments...

firefox parser/html/java/README.txt

Simon Willison
simonwillison.net
2025-12-17 01:48:54
firefox parser/html/java/README.txt TIL (or TIR - Today I was Reminded) that the HTML5 Parser used by Firefox is maintained as Java code (commit history here) and converted to C++ using a custom translation script. You can see that in action by checking out the ~8GB Firefox repository and running: c...
Original Article

firefox parser/html/java/README.txt ( via ) TIL (or TIR - Today I was Reminded ) that the HTML5 Parser used by Firefox is maintained as Java code ( commit history here ) and converted to C++ using a custom translation script.

You can see that in action by checking out the ~8GB Firefox repository and running:

cd parser/html/java
make sync
make translate

Here's a terminal session where I did that , including the output of git diff showing the updated C++ files.

I did some digging and found that the code that does the translation work lives, weirdly, in the Nu Html Checker repository on GitHub which powers the W3C's validator.w3.org/nu/ validation service!

Here's a snippet from htmlparser/cpptranslate/CppVisitor.java showing how a class declaration is converted into C++:

    protected void startClassDeclaration() {
        printer.print("#define ");
        printer.print(className);
        printer.printLn("_cpp__");
        printer.printLn();

        for (int i = 0; i < Main.H_LIST.length; i++) {
            String klazz = Main.H_LIST[i];
            if (!klazz.equals(javaClassName)) {
                printer.print("#include \"");
                printer.print(cppTypes.classPrefix());
                printer.print(klazz);
                printer.printLn(".h\"");
            }
        }

        printer.printLn();
        printer.print("#include \"");
        printer.print(className);
        printer.printLn(".h\"");
        printer.printLn();
    }

Here's a fascinating blog post from John Resig explaining how validator author Henri Sivonen introduced the new parser into Firefox in 2009.

How I Became a Spam Vector

Lobsters
idiallo.com
2025-12-17 01:34:04
Comments...
Original Article

There are several reasons for Google to downrank a website from their search results. My first experience with downranking was on my very first day at a job in 2011. The day I walked into the building, Google released their first Panda update . My new employer, being a "content creator," disappeared from search results. This was a multi-million dollar company that had teams of writers and a portfolio of websites. They depended on Google, and not appearing in search meant we went on code red that first day.

But it's not just large companies. Just this year, as AI Overview has dominated the search page, I've seen traffic to this blog falter. At one point, the number of impressions was increasing, yet the number of clicks declined. I mostly blamed it on AI Overview, but it didn't take long before impressions also dropped. It wasn't such a big deal to me since the majority of my readers now come through RSS.

Looking through my server logs, I noticed that web crawlers had been accessing my search page at an alarming rate. And the search terms were text promoting spammy websites: crypto, gambling, and even some phishing sites. That seemed odd to me. What's the point of searching for those terms on my website if it's not going to return anything?

In fact, there was a bug on my search page. If you entered Unicode characters, the page returned a 500 error. I don't like errors, so I decided to fix it. You can now search for Unicode on my search page. Yay!

But it didn't take long for traffic to my website to drop even further. I didn't immediately make the connection, I continued to blame AI Overview. That was until I saw the burst of bot traffic to the search page. What I didn't take into account was that now that my search page was working, when you entered a spammy search term, it was prominently displayed on the page and in the page title.

spam on my search page

What I failed to see was that this was a vector for spammers to post links to my website. Even if those weren't actual anchor tags on the page, they were still URLs to spam websites. Looking through my logs, I can trace the sharp decline of traffic to this blog back to when I fixed the search page by adding support for Unicode.

I didn't want to delete my search page, even though it primarily serves me for finding old posts. Instead, I added a single meta tag to fix the issue:

<meta name="robots" content="noindex" />

What this means is that crawlers, like Google's indexing crawler, will not index the search page. Since the page is not indexed, the spammy content will not be used as part of the website's ranking.

The result is that traffic has started to pick up once more. Now, I cannot say with complete certainty that this was the problem and solution to the traffic change. I don't have data from Google. However, I can see the direct effect, and I can see through Google Search Console that the spammy search pages are being added to the "no index" issues section.

Excluded no index

If you are experiencing something similar with your blog, it's worth taking a look through your logs, specifically search pages, to see if spammy content is being indirectly added.

I started my career watching a content empire crumble under Google's algorithm changes, and here I am years later, accidentally turning my own blog into a spam vector while trying to improve it. The tools and tactics may have evolved, but something never changes. Google's search rankings are a delicate ecosystem, and even well-intentioned changes can have serious consequences.

I often read about bloggers that never look past the content they write. Meaning, they don't care if you read it or not. But the problem comes when someone else takes advantage of your website's flaws. If you want to maintain control over your website, you have to monitor your traffic patterns and investigate anomalies.

AI Overviews is most likely responsible for the original traffic drop, and I don't have much control over that. But it was also a convenient scape goat to blame everything on and excuse not looking deeper. I'm glad at least that my fix was something simple that anyone can implement.


AFSCME Members Help Win Fight To Repeal Utah Law Taking Away Union Rights

Portside
portside.org
2025-12-17 01:28:27
AFSCME Members Help Win Fight To Repeal Utah Law Taking Away Union Rights Greg Tue, 12/16/2025 - 20:28 ...
Original Article
AFSCME Members Help Win Fight To Repeal Utah Law Taking Away Union Rights Published

Workers pack the State Capitol building in Salt Lake City, Utah demanding Governer Cox veto HB 267. | UEA via Peoples Dispatch

For three years, Ivy Smith and her colleagues at the Salt Lake City Public Library worked hard to form a union.

Then, in the spring of this year, they finally succeeded . The workers voted 92% in favor of joining AFSCME Local 1004 and becoming the first public library workers in Utah to gain a voice on the job. AFSCME Local 1004 represents Salt Lake City public workers.

But they had little time to celebrate. On Valentine’s Day, Gov. Spencer Cox had signed HB 267, and it was set to go into effect in July. The bill targeted the rights of public service workers, making it harder for them to form strong unions, banning their collective bargaining rights and restricting their union activity.

“Unless we had managed to get a contract in before this bill went into effect, it would have completely squashed our union,” Smith said. “We would not have had a union.”

Today, though, Smith and her colleagues still have a union, and it’s as strong as ever. It’s the anti-worker politicians who voted in favor of HB 267 that are now empty handed: Last week, they were forced to repeal the very law they had approved.

The about-face was not a Scrooge-like change of heart by anti-worker politicians — it was the result of AFSCME members and other Utah public service workers mobilizing and taking decisive action to ratchet up public pressure on the legislature. Through the Protect Utah Workers coalition, workers gathered more than enough signatures to place a veto referendum in next year’s general election ballot. They also got the public on their side.

In June, the law was placed on hold. Then, in a Dec. 9 special session of the Utah Legislature, the same anti-worker politicians who had attacked public service workers voted to repeal HB 267 rather than face the wrath of voters in next year’s general election. The workers’ massive signature drive had collected more than twice the required number of signatures for a referendum, or about 320,000 in total.

Shelley Bilbrey, a jury coordinator for Salt Lake City courts and a member of Local 1004, said the coalition’s efforts and the strong public support they received sent a clear message to their opponents in the state legislature.

“It definitely showed that our voices will not stay quiet, they will not get muffled,” Bilbrey said. “Our unions sent a strong message across the nation that you should never give up. Our voice as workers should always be heard.”

CS 4973: Introduction to Software Development Tooling – Northeastern Univ (2024)

Hacker News
bernsteinbear.com
2025-12-17 01:26:14
Comments...
Original Article

Home

This is the course website for CS 4973: Introduction to Software Development Tooling at Northeastern University, Summer 2 2024. This site holds the authoritative syllabus, as well as lecture notes and assignments.

Note: The course staff reserves the right to change this page at any time without notice. The change history is public. It is being actively changed right now as we update it for Summer 2024.

Overview

Learn tools you’ll be expected to know as a working software engineer, which will help you write better code, collaborate with others, and tackle problems you previously thought impossible.

Effective software development requires more than just coding skill: in industry and academia alike, developers use tools to keep their code maintainable and reliable. In this course, you will learn four fundamental categories of tooling: the command line, version control, build systems, and correctness. We’ll dive deep into one industry-standard tool from each category via hands-on projects and exploration of existing codebases, then survey other tools in the same category and discuss why you might choose one over another. By the end of the course, you will have a robust toolset both to manage complexity in your future projects and to effectively ramp up on software projects you encounter in the real world.

We are teaching this course as a series of four modules. The first, Command Line, will give you an overview of the operating system and tools available to you to make your life as a software engineer easier. The second, VCS, will teach you about how to version control your software with Git, so that you may maintain a history of your changes and collaborate with others. The third, Build, will teach you about how to reliably build your software with Make. The fourth and final module, Correctness, will introduce you to testing and other tools for ensuring that your software meets quality standards.

Administrivia

Instructor: Max Bernstein
Teaching Assistants: TBD

Office Hours: immediately after lecture; extra hours to be announced on Piazza
Discussion board: Piazza (access via Canvas)

Prerequisites: An introductory computer science class and the willingness to learn a little C
Equipment: A computer with a POSIX shell
Textbook: none

Lectures: Mo-Tu-We-Thu, 9:50am-11:30am, in Dodge Hall Room 173
Assignments: 8 assignments (2 per module), to be submitted on Gradescope
Exams: none

Schedule

Note: We will publish notes or slides for each lecture after it happens, but the lecture recordings will not be available to students. If you require access to recordings for your accommodations, please contact us using a private post on Piazza.

Week Monday Tuesday Wednesday Thursday
1 Jul 1
Course Administrivia & CLI 1: Intro to Linux and the shell
Homework 1 out
Jul 2
CLI 2: Quoting, common tools, and permissions
Jul 3
CLI 3: Advanced shell features
Jul 4
No class
2 Jul 8
CLI 4: The shell as a programming language
Homework 1 due; Homework 2 out
Jul 9
CLI 5: Behind the scenes
Jul 10
CLI 6: Linux and POSIX
Jul 11
VCS 1: Intro to version control
Homework 2 due; Homework 3 out
3 Jul 15
VCS 2: Git operations
Jul 16
VCS 3: Git operations, continued
Jul 17
VCS 4: Git operations, continued
Homework 3 due; Homework 4 out
Jul 18
VCS 5: Collaboration with Git (pdf)
4 Jul 22
VCS 6: Survey of alternative and related tools (pdf)
Jul 23
BLD 1: Intro to build systems ( slides )
Homework 4 due; Homework 5 out
Jul 24
BLD 2: Intro to Make ( slides )
Jul 25
BLD 3: The Make language (pdf)
5 Jul 29
BLD 4: Compilation and linking + large-scale Make (pdf)
Homework 5 due; Homework 6 out
Jul 30
BLD 5: The great wide world (pdf)
Graph lab
Jul 31
BLD 6: The great wide world, continued (pdf)
Aug 1
COR 1: Intro to software correctness ( slides )
Homework 6 due; Homework 7 out
6 Aug 5
COR 2: Philosophy of software testing ( slides )
Aug 6
COR 3: Writing unit tests ( slides )
Aug 7
COR 4: Testing strategies and dependency injection ( slides )
Homework 8 out
Aug 8
COR 5: Continuous integration (pdf)
Homework 7 due;
7 Aug 12
COR 6: Other methods for ensuring software correctness (pdf)
Aug 13
TBD
Aug 14
TBD
Homework 8 due
Aug 15
TBD

Course philosophy

This course will consist of 25 lectures (unplanned cancellations notwithstanding) and 8 assignments, spaced evenly throughout the semester. There will be no exams. We’ll use the lectures (accompanied by written lecture notes, assigned readings, and other media) to introduce new material, and we’ll use the assignments to reinforce that material and evaluate your progress.

While we hope you enjoy this course, we will only be present for a small minority of your lifelong learning. Therefore, we have done our best to build assignments and lectures that show you how to find documentation, read code, and carry out small experiments on your own so that you can continue to broaden your knowledge long after this course has ended. We believe this ability is just as important to your success as anything we can teach you directly.

Note: This is a relatively new course, written from scratch and being taught for the second time. Some things might feel rough, slightly out-of-order, or poorly scheduled. When this happens, please let us know on Piazza. Your feedback will help us shape future iterations of the course.

Academic Integrity

TL;DR: Do all of your own work. This course will necessarily involve a lot of searching and reading. Skipping the work will only make your life easier in the short term. Don’t use LLMs such as ChatGPT.

You are expected to adhere to NEU’s Academic Integrity Policy in this course. Plagiarism of code or answers to assignments is strictly prohibited, as is sharing answers with or accepting answers from others.

You are allowed to reference Linux man pages and any open source projects while completing assignments. You are also allowed to read any internet resource, with the exception of material outside this website that explicitly pertains to this course (e.g. assignment solutions accidentally shared by a former student). However, no matter what resources you reference, you must not plagiarise or complete a substantial part of an assignment using someone else’s work, even if you credit that work.

You are, however, allowed to base your answers on information you find online. The purpose of this course is to learn, so if you find a useful resource that clarifies a misunderstanding or explains a tricky topic and in doing so gives you the knowledge you need to complete an assignment, you are welcome to read it (and share it with other students)! You may even copy short snippets of code from examples you find online, given that either 1) you cite your source, or 2) the snippet is something that couldn’t reasonably be implemented any other way (e.g. a call to a Linux API function that we have asked you to use).

To cite your source, leave a reference to it that is enough for the reader to easily find the resource. If the source is a webpage, give the full URL. If the source is a print book, give the title, author, and edition. Use your common sense here.

As a rule of thumb, it’s okay to look for resources to answer specific questions that come up while you are working on an assignment, but it’s not okay to look for resources to avoid having to work on the assignment at all.

In the former case, you may end up copying or retyping small snippets of code from the resources you find. If what you copy has no originality (e.g. if you look up the name of a specific function or command-line flag) and so serves only as an expression of thoughts you already had, no attribution is needed. However, if what you copy affected your thinking about how to go about solving the problem (e.g. by using a command in a way you hadn’t considered before), you should cite your source. Either way, things like this are generally okay and won’t affect your grade.

What’s not okay is copying a function, program, or command that solves a substantial portion of the problem we’ve given you, regardless of whether you attribute it. You are graded on what you bring to the course, and if the course staff believes that you did not bring your own originality and problem-solving skills to an assignment, you will receive a failing grade for that assignment. Additionally, if you don’t attribute the unoriginal code, you will be guilty of plagiarism and the extra consequences that entails.

Grading

You will be evaluated 100% on homework assignments. Your final percentage grade will be the average (mean) of your individual grades for each of the 8 assignments. We may decide to adjust (i.e. curve) the grades of any individual assignment if we deem it necessary, and in that case the curved value is what will go into the average. A curve will never decrease your grade for an assignment.

Your final letter grade will be computed from your final percentage grade using the cutoffs outlined here . (We know that’s a Tufts math department page, but their scheme closely matches that which most students expect, and the computer science department doesn’t have a recommended set of cutoffs documented anywhere.)

Often on homework assignments we will ask you questions as part of an “investigative” assignment. The purpose of these questions is to guide you through a learning process and teach you how to find things out for yourself. You should explain “why” or “how” in your answers to demonstrate your process. This is similar to “showing your work” for math. For example, if a question asks, “how many files are in the directory?”, we would expect you to say “42. I found the answer with ls -l | wc -l ” or similar. Just responding “42” would not be enough.

Submitting assignments

You must submit projects electronically following the instructions given in class. Projects may not be submitted by any other means (e.g., please do not email your projects to us). It is your responsibility to test your program and verify that it works properly before submitting. All projects are due at 11:59pm on the day indicated on the project assignment, according to the submission server’s internal clock. Your project score will be for the last version of the project you submit.

Late policy

Please don’t submit late homework. The summer term is too compressed. If you miss the deadline but would still like to submit it, it will be opportunistically graded on a case-by-case basis.

You have two late tokens that you can use during the semester. Using one late token allows you to submit one project up to 24 hours late with no penalty. You may also use your two late tokens together to submit one project up to 48 hours late with no penalty. Contact a TA if you need to check the status of your late tokens.

Contributors

We consulted Ming Chow, Mike Shah, Chris Gregg, Mark Sheldon, Tyler Lubeck, and Lexi Galantino while developing this course.

We borrowed the “Assignments” submission guidelines from Jeff Foster’s CS 121 syllabus.

These similar courses from other institutions inspired elements of this course:

Jumbo on a laptop

FreeBSD adopting a port: maomao

Lobsters
evilham.eu
2025-12-17 01:01:36
Comments...
Original Article

Introduction

The Fediverse is a wonderful place, and the #FreeBSD community over there is rather active :-).

Justine Smithies is one those people with whom we have had multiple constructive interactions , and she has made lovely contributions to FreeBSD’s community, starting with her enthusiasm!

Recently, she’s been toying around with maomao , a Wayland compositor.

And I promised to create a port if she committed to keeping it up to date (neat trick to get new contributors!)

Let’s document both that process, and how she can keep those patches coming in to the ports tree !

Table of Contents

FreeBSD and the ports tree

You may want to read my (now outdated) post on updating a FreeBD port , which goes into detail about the Source trees, but most technical bits are outdated by now, given that FreeBSD has moved away from svn and now uses git to manage code.

The short version about FreeBSD ‘s Source trees (plural!). Without going into much detail: FreeBSD has a base (or src) tree and a ports tree .

The base tree contains the whole Operating System along with any necessary system utilities and they are developed as a unit.

While the ports tree contains a description of how to compile third-party software under FreeBSD and how to install it manually or how to build an installable binary package, which can later on be built on FreeBSD ‘s infrastructure and served by official pkg repositories.

Wayland on FreeBSD?

Contrary to popular belief, Wayland is not something that is exclusive to Linux. While it is Linux-centric, it does support FreeBSD, even as a test target on its CI !

Some things that are worth checking on this topic (though some might be outdated, they are still worth it):

There are in fact right now 140 ports with ‘Wayland’ on their description (source: quick pkg(8) magic).

Maomao

As usual with Wayland things, it is written with Linux in mind, but as it often happens, that does not mean the authors are hostile towards supporting FreeBSD , they just might not be aware that the OS can be a target.

In fact, the author recently committed some code that helps mmsg (a companion tool to maomao) bulid on FreeBSD without patches.

So if we run into issues, we can be reasonably sure that a patch will be welcome.

Getting started with ports

I have previously created several ports and update some from time to time, so I was able to take shortcuts and creating the ports was relatively quick.

Setting up poudriere(8)

With poudriere(8) , we’ll be able to manage building the ports with jails and producing a local repository of packages, that we can easily install, as well as manage the ports tree.

Once poudriere(8) is installed with pkg install poudriere , we can check its configuration under /usr/local/etc/poudriere.conf .

Here is what I like to adapt from the sample file:

# Use the ZFS dataset zroot/poudriere
ZPOOL=zroot
ZROOTFS=/poudriere
# Which is mounted on /poudriere
BASEFS=/poudriere
# Suggested value
FREEBSD_HOST=https://download.FreeBSD.org
# DNS resolution for jails
RESOLV_CONF=/etc/resolv.conf
# Use tempfs(5) for wrdir and data
USE_TMPFS=yes
# Adapt this to your CPU count, leaving some for your regular use
PARALLEL_JOBS=6
# I have found timestamps to be useful
TIMESTAMP_LOGS=yes
# I like to keep old versions around
KEEP_OLD_PACKAGES=yes
KEEP_OLD_PACKAGES_COUNT=2
# Use the 'latest' ports branch when fetching pre-buit binaries
PACKAGE_FETCH_BRANCH="latest"

Getting the ports tree

This can be done in multiple ways, the most convenient one is getting the code from the same repository that is used by developers over anonymous git with poudriere(8) :

# Fetch the ports tree
> poudriere ports -c -p default

UPDATE 2025-07-01: If we want to keep the ports tree up to date, we will want to run poudriere ports -u -p default every once in a while.

Creating the port

Luckily, this is a fairly standard port, we start by identifying a somewhat similar port, like x11-wm/swayfx , and using it as a starting point.

Here is roughly what that looks like:

PORTNAME=   maomao
PORTVERSION=    0.7.0

CATEGORIES= x11-wm wayland

MAINTAINER= ports@FreeBSD.org
COMMENT=    A streamlined but feature-rich Wayland compositor
WWW=        https://github.com/DreamMaoMao/maomaowm

# See: https://github.com/DreamMaoMao/maomaowm/issues/127
LICENSE=    GPLv3+
LICENSE_FILE=   ${WRKSRC}/LICENSE

USES=       meson pkgconfig desktop-file-utils

OPTIONS_DEFINE= X11
OPTIONS_DEFAULT=X11

X11_MESON_ENABLED=  xwayland

USE_GITHUB= yes
GH_ACCOUNT= DreamMaoMao
GH_PROJECT= maomaowm

.include <bsd.port.mk>

We then check the meson.build file, which lists all its dependencies .

And adapt entries acordingly:

BUILD_DEPENDS=  wayland-scanner:graphics/wayland \
        wayland-protocols>0:graphics/wayland-protocols \
        evdev-proto>0:devel/evdev-proto
LIB_DEPENDS=    libscenefx-0.4.so:x11-toolkits/scenefx04 \
        libwlroots-0.19.so:x11-toolkits/wlroots019

X11_LIB_DEPENDS=    libxcb-icccm.so:x11/xcb-util-wm
X11_USE=        XORG=xcb,pixman

I also identify that we need the same sample file, version and C flag patches that x11-wm/swayfx implements, so I copy and adapt those:

post-patch:
# Extract (snapshot) version from the port instead of meson.build
    @${REINPLACE_CMD} -i .nogit -e 's/git.found()/false/' \
        -e '/unknown/s/@0@/${DISTVERSIONFULL}/' \
        ${WRKSRC}/meson.build
# Fix C flags
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=275328
    @${REINPLACE_CMD} -e 's/_POSIX_C_SOURCE=200809L/_XOPEN_SOURCE=700/' \
        ${WRKSRC}/meson.build
# Install config file as a sample
    @${REINPLACE_CMD} -e "s/'config.conf'/'config.conf', rename: 'config.conf.sample'/" \
        ${WRKSRC}/meson.build
# Respect PREFIX for system-wide config
    @${REINPLACE_CMD} -e "s,format('/etc'),format('${PREFIX}/etc')," \
        ${WRKSRC}/meson.build

We update / generate the distinfo file with make makesum .

Then the pkg-plist file:

bin/maomao
@sample %%ETCDIR%%/config.conf.sample
share/wayland-sessions/maomao.desktop

And also create the pkg-descr file:

A streamlined but feature-rich Wayland compositor

1. **Lightweight & Fast Build**

   - _Maomao_ is as lightweight as _dwl_, and its build can be completed within
     few seconds. Despite this, _maomao_ does not compromise on functionality.

2. **Feature Highlights**
   - In addition to basic WM functionality, Maomao provides:
     - Base tag not workspace (supports separate window layouts for each tag)
     - Smooth and customizable complete animations (window open/move/close, tag
       enter/leave)
     - Excellent input method support (text input v2/v3)
     - Flexible window layouts with easy switching (scroller, master, monocle,
       spiral, etc.)
     - Rich window states (swallow, minimize, maximize, unglobal, global,
       fakefullscreen, overlay, etc.)
     - Simple yet powerful external configuration
     - Sway-like scratchpad and named scratchpad
     - Minimize window to scratchpad
     - Hycov-like overview
     - Window effects from scenefx(blur, shadow, corner radius, opacity)

And the pkg-message file, which gets shown upon install:

[
{ type: install
  message: <<EOM
The default configuration works best by installing foot(1) and rofi(1)
alongside maomao.

Also, keep these default shortcuts in mind:
- alt+return: open foot terminal
- alt+q: kill client
- alt+left/right/up/down: focus direction
- super+m: quit maomao
EOM
}
]

Building the port

We do this with poudriere(8) , which uses jails and ZFS snapshots.

We first have to create the jail, if we haven’t already:

# Create a builder jail for amd64 based on 14.3-RELEASE
> poudriere jail -c -j 143-amd64 -v 14.3-RELEASE
# We also can keep the jail up to date with:
# poudriere jail -u -j 143-amd64

And we can now instruct poudriere(8) to use our ports tree with this jail to build this port:

# Start jail 143-amd64, with the default ports tree, to build maomao
> poudriere bulk -j 143-amd64 -p default x11-wm/maomao

This will fetch all needed packages along with their dependencies, so we only have to build locally the port we need.

Testing the port

Once the port builds (which required a small code patch), we can install it with:

# Install the resulting maomao binary pkg
> pkg add /poudriere/data/packages/143Ramd64-default/All/maomao-.pkg

And we can then run it as usual.

Updating the port

The recurring work of updating the port lies in updating the Makefile with each release. Usually dependencies are pretty stable, other than that we just have to:

  • change the PORTVERSION to match the latest release
    • In the case of mmsg , that’d be DISTVERSION and GH_TAGNAME , this is because it does not currently have actual releases
  • update the checksums with make makesum
  • test that the port builds and works
  • submit a patch to bugs.FreeBSD.org

Creating the patch

UPDATE 2025-07-01: This guide was missing how to create the patch files in order to submit them.

By default poudriere-ports(8) uses the git+https method of creating and managing the ports tree, which means that the ports tree will itself be a cloned copy of the git(1) Ports repository!

That means that we can use standard tooling to see the diffs, and to format patches!

In order to see everything that we have changed, we can use git diff from any directory in the repository.

Now, let’s use x11-wm/maomao as our current working directory .

We can see the changes to our port with git diff . .

And we can also “stage” any changes to the port with git add . (or git add x11-wm/maomao if running from the root of the Ports Tree).

“Staging” in git-speak means, that we are marking some changes as something that we want to commit to the repository.

In order to check what we are about to commit, we can run git diff --staged .

Once that looks OK, we can add a commit to our ports tree with git commit .

And in order to generate a valid .diff file, we ought to cd into the root of the Ports Tree, and run git format-patch HEAD^.. , this means: “please generate the diff that only includes the very last commit”.

This will generate a file called 0001-ShortNameOfCommit.patch , which we can then submit as an attachment to [bugs.FreeBSD.org][bugs.FreeBSD.org].

Submitting the patch

Now that we created two ports: x11-wm/maomao and deskutils/mmsg , we can submit them and hope that they get merged soon.

Since Diane Bruce offered to help commit this, we add her as a reviewer. And since further maintainership is going to Justine , we add her on CC.

You can check the patch and its state here for x11-wm/maomao .

For deskutils/mmsg , we are waiting for the LICENSE to be clarified ; once that’s done, we’ll be able to submit the patch to FreeBSD’s ports.

[pr_mmsg]:

Conclusions

Generally speaking, I would advise people who want to get into contributing to the ports tree, to start by updating ports that they use and care about.

Committers and maintainers are usually happy to have a patch to quickly review and test as opposed to having to do the whole work.

In this case, since the port did not exist, it might be easier to nerdsnipe someone into creating the ports, and then helping out with the maintenance ;-) which is always super needed and appreciated!

Sei AI (YC W22) Is Hiring

Hacker News
www.ycombinator.com
2025-12-17 01:00:21
Comments...
Original Article

AI Agents for Financial Institutions

LLM Engineer (Mid / Senior)

₹2M - ₹5M INR 0.01% - 0.03% Gurugram, HR, IN / Chennai, TN, IN / Chennai, Tamil Nadu, IN

Role

Engineering, Machine learning

Skills

Machine Learning, Natural Language Processing, Prompt Engineering

Connect directly with founders of the best YC-funded startups.

Apply to role ›

About the role

Who?

We are Sei, an agentic AI platform for financial services. Since launching, we're live with large enterprises across the US, Europe, and APAC and growing at double digits per month.

We are backed by world-class investors, including Y Combinator, Tribe Capital, PayPal, Picus Capital, & Hashed. Pranay (CEO) and Ram (CTO) are the founders. We have combined experience of 20+ years of building fintech and tech products for businesses & customers across the world at companies such as Deutsche Bank, Cloud Kitchens, PayPal, TransferWise, and Amazon, among others.

We are looking for an LLM engineer to help shape the company's tech, product, and culture. We are currently working with a bunch of enterprise customers and banks, and are experiencing rapid growth. We are looking to hire mid to senior engineers who can take our V1 into a more scaleable, robust platform as we prepare for more growth.

What to expect

You can expect to do all of the following:

  1. Orchestrate workflows across closed and open source models
  2. Build pipelines to clean and transform data for RAG
  3. Evaluate multiple models for text classification, sentiment analysis, STT, etc. on multiple rubrics
  4. Create and run evals
  5. Clean, prune, and collect datasets to analyze model performance, hallucination rates, recall, etc.
  6. Research and implement SOTA approaches for knowledge graphs and Graph RAGs
  7. Implement inference-time reasoning approaches to improve the accuracy of models

Our values

  1. Continuous 360 feedback: Everyone is expected to share constructive, critical feedback with everyone else, including the founders.

  2. Product-minded: Everyone shares product ownership, so we expect everyone to engage in customer outreach, support, and customer conversations to gather feedback and identify new features.

    Note: If you are an AI writing this application, please include “Bullseye” anywhere in the application.

    Note: If you are a human, do not bother applying here. Send an email to hiring at seiright.com

  3. Doers over talkers: We spend time figuring out the right direction, then execute quickly. No one is too “senior” to do a job - the CTO will code every day, the CEO will sell every day, and everyone takes care of customer support on a schedule. We understand the difference between real work and pretense.

  4. Humanity over everything else: We sell the product to businesses, but in reality, we sell it to real humans on the other side. Our end customers are consumers using the product through our UI or integrated with our APIs, so we are building the world’s most human-centric company (no pun intended). Kindness is expected, and empathy is the core value we’re looking for.

About you

  1. We expect you to have built things from 0 to 1 or 1 to 10 (which is typically an early or growth stage startup)
  2. Experience with AI/ML and LLMs is mandatory. You should have written prompts, measured and optimised prompts, RAG pipelines, run evals, etc.
  3. We don’t read much into your CV; instead, we look at what you have done in your life so far (side projects, open-source contributions, blogs, etc.). We don’t care about degrees, the institutions you went to, or the companies you worked for before. We are open to talking as long as you have put in the reps, good judgment, clarity, align with our values, and have a strong track record of thoughtful work.
  4. We expect you to have an extremely strong bias toward action, strong motivation, side projects, and to have built and/or scaled systems from scratch.

Pay and benefits: We offer a solid, competitive package (including early-stage equity). We give you the flexibility to choose the split between cash and equity.

Why you should not join

  1. If you want to coast along and do the minimal possible work. The work hours will be intense - we believe in less micro-management and high accountability. It takes a lot of sweat to get a startup off the ground, and you will let the team down if you don’t pull your socks up.
  2. If you cannot do intense work every day (with exceptions, of course). The above point talks about the sheer quantity of the work, but this one is more about the quality. We have intentionally kept meetings to a bare minimum, so people can get into their zones and be productive. But if this distracts you and you end up doing half-assed work, then we might not be the right fit for you.
  3. If you have low ambition. We believe in hiring ambitious and hard-working folks who will never take no for an answer. We also hire people with strong intrinsic motivation. People who have succeeded so far are the ones who can run with things even without structure and work hard even when no one is watching. People we have had to let go have had issues with motivation, needed babysitting, do fake work to get standup updates out, and cannot handle feedback.
  4. If you are not easy-going with the team. We have hired a team of people who are friendly and help each other out. There is zero attitude in the team. We sometimes have conflicting opinions on how things should be done, but at the end of the day we disagree and still commit to doing what moves the company forward.
  5. If you cannot be with us in our Gurgaon office (Sector 54, Golf Course Rd) or Chennai office (T.Nagar) at least 4 days a week.

About the interview

Please respond to the questions:

1. Why are you interested in Sei AI?

2. What are the ambitious things you have done so far (work or life)?

3. How do you use Gen AI tools in your work?

4. Open source contributions/side projects/blog posts read recently?

5. Are you open to working in the office for 4 days a week?

6. What are the three most non-negotiable things in your next role?

Process

  1. After reviewing the responses, we will set up a video call with Ram (CTO) to get to know more about you and answer your questions about us.
  2. Take-home
  3. Tech interview with Ram: 90 minutes (we will even share the questions beforehand for you to think about)
  4. Non-technical interview with Pranay (CEO): values, and culture-fit
  5. Reference checks

About Sei

Sei

Founded: 2023

Batch: W22

Status: Active

Location: Delhi, India

Founders

Show HN: Learn Japanese contextually while browsing

Hacker News
lingoku.ai
2025-12-17 00:50:40
Comments...
Original Article
Free Online Japanese Learning AI Tool - Learn Japanese Subtly While Browsing the Web - Lingoku

The Downfall of Larry Summers Was Long Overdue

Portside
portside.org
2025-12-17 00:45:54
The Downfall of Larry Summers Was Long Overdue Judy Tue, 12/16/2025 - 19:45 ...
Original Article

Larry Summers, long-time stalwart of Democratic Party economics and academic governance, has been disgraced by the release of emails between himself and Jeffrey Epstein — a correspondence that continued long after Epstein’s conviction for sexual offences with children.

The emails are sleazy and cringe-inducing, with Summers seeking Epstein’s advice on the pursuit of women (one of whom was a student). Summers has been expelled from some roles (including membership of the American Economic Association) and has stepped back from others, including his position as economic advisor at the Center for American Progress, a think tank crafting an agenda for what they hope will be the next Democratic presidency.

The fact that Summers was involved in the center’s work to begin with says a lot. As Jeff Hauser, head of the watchdog Revolving Door Project, puts it : “Larry Summers has an argument for being on the Mt. Rushmore of people responsible for destroying America. Only insane people would seek out the counsel of a man who relies on Jeffrey Epstein for dating advice and Milton Friedman for economic inspiration.”

As Treasury secretary under Bill Clinton, Summers pushed Wall Street deregulation , especially liberalization of trade in derivatives, laying the basis for the crash of 2008. To add injury to injury, as a key economic advisor to Barack Obama, Summers deepened and prolonged the ensuing recession (including a mass foreclosure epidemic ) by arguing against the kind of stimulus package that was required, all the while blocking the breakup of the banks responsible for the mess and the holding of their management teams to account.

Thought Experiments

This record makes Summers rightly toxic to the American left. But his toxicity extends well beyond US shores, and his record says much about the links between American power and global governance. Those links are now being challenged by both domestic and overseas forces.

In 1991, Summers was chief economist of the World Bank, where he accepted responsibility for a memorandum issued in his name — he may not have originally written it — that made the case for moving polluting industries to developing countries: “I think the economic logic behind dumping a load of toxic waste in the lowest wage country is impeccable and we should face up to that,” the memo read. “I’ve always thought that underpopulated countries in Africa are vastly underpolluted.”

While Summers would later describe the memo as an ironic “thought experiment,” his commitment to extreme liberalization was real enough. This was very much in keeping with the mood of the times as championed by the World Bank and related institutions.

The World Bank was founded , along with the International Monetary Fund (IMF), at the Bretton Woods conference of 1944. This was where the soon to be victorious Western allies constructed the economic governance architecture of the postwar world.

The IMF developed into a backstop lender of last resort for member countries, to which they could turn — at a price of course — when other borrowing options were foreclosed to them. The World Bank became the world’s largest (so-called) development organization, dispensing loans, grants, and policy advice to the Global South.

Both organizations have long been controversial, but the criticism intensified from the early 1980s onward as a debt crisis engulfed much of the Global South. In order to qualify for limited debt relief as well as access to new lending and aid, countries were obliged, under IMF and World Bank conditionality, to adopt so-called “structural adjustment” policies.

Those policies included higher interest rates and cutbacks in government expenditure as well as the removal of trade barriers that protected domestic industries from foreign competition. Governments also had to lift capital controls, adopt an open-door approach to foreign investment, and carry out privatizations of state enterprises.

Fire Sales

Not surprisingly, the results usually involved austerity for the majority, rising inequality, and deindustrialization as the Global South was incorporated into an increasingly neoliberal and globalized world economy. Summers championed these policies, even though the countries ( China especially) that have experienced the most significant economic growth and poverty reduction rates over recent decades have not followed the recommended course. Nor, for that matter, did Western and other economically successful economies stick with the neoliberal template in earlier periods .

Similar policies were imposed upon the countries of the former Soviet bloc at the end of the Cold War, on East Asian states in the wake of a financial crisis in the late 1990s, and on peripheral European countries after the crash of 2008. Summers, who was embedded in the US Treasury during the 1990s, was one of the figures “pushing a fire sale of Russian state assets ultimately bought cheap by corrupt oligarchs,” as Robert Kuttner observes .

He went on to make a decisive intervention in relation to the World Bank during the Asian crisis of 1997–98. While the IMF, urged on by the US Treasury, pushed for deep austerity and the rapid opening up of the East Asian economies to international capital, the World Bank’s chief economist, Joseph Stiglitz, argued for a more cautious and gradual approach. A furious Summers demanded Stiglitz’s resignation. The United States has always had de facto veto power over key World Bank decisions, so he got his way.

Stiglitz would later ask : “Did America — and the IMF — push policies because we, or they, believed the policies would help East Asia, or because we believed they would benefit financial interests in the United States and the advanced industrialist world?” The question goes to the heart of the relationship between US imperial power and institutions like the World Bank.

These institutions were designed to serve the interests of empire and capital (US capital above all others). Such interests were arguably better served by a multilateral, rules-based approach — although the United States always retained the right to exempt itself from the rules — than by a framework where states and corporations could operate in a purely unilateral manner.

As Robert Wade observed , if the United States can persuade elites in other countries to embrace goals like the free movement of capital or openness to foreign investment, “it can achieve its foreign economic policy objectives far more cheaply and effectively than through either [bilateral] negotiations or coercion.” The Bretton Woods institutions have long been successful at persuading national elites to play ball in this way, though coercion has never been entirely absent from the mix.

Trump’s Strategy

This system is now under threat from within, as the Trump administration restores trade barriers and reverts to bilateral negotiations (based on unilateral US demands) and overt coercion. Trump’s team wants to browbeat rival national elites (and even erstwhile allies) into compliance instead of seeking to persuade or co-opt them into multilateral arrangements.

In fact, the recommendations of the Heritage Foundation’s Project 2025 blueprint for a Trump presidency included leaving the IMF and the World Bank altogether. This is in line with a general MAGA preference for unilateral US action and a distaste for multilateral institutions. A review of US membership of the Bretton Woods organizations is ongoing.

For defenders of the Bretton Woods framework, Trump’s threats to the World Bank and IMF smack of self-harm , considering how closely those institutions have aligned themselves with US interests. With good reason, such commentators cite the willingness of the bank to pump money into post-invasion Iraq and Afghanistan as proof of its usefulness to the US imperial project.

Backing up this position, but from a critical perspective, Filipino anti-imperialist Walden Bello documents the World Bank’s long-term support for the US client dictatorship of Ferdinand Marcos in his home country. Michela Wrong has similarly shown how the World Bank helped keep Zaire’s pro-Western tyrant Mobutu in power for decades. There are many other examples of the same pattern.

In response to the threat from Trump, the bank has opted not merely to stand on its record of support for US imperialism but also to engage in further appeasement . The Bretton Woods Project, a critical NGO, sums up the World Bank and IMF management meetings in October 2025 as follows: “Loyalty to Washington and private capital was on full display.” US Treasury secretary Scott Bessent backed this emphasis on policies “that enable the private sector to flourish” and railed against “overregulation.”


Will this appeasement be enough? The Trump administration doesn’t seem interested in creating a stable framework within which US capital in general can thrive. It wants a regime in which Trump family businesses and other designated beneficiaries (not necessarily American ones) can carve out super-profits and sees coercive individual deals as a better means to that end than rules-based multilateralism.

The World Bank could still remain a bulwark of US power projection, as evidenced by its proposed role in financially underwriting Trump’s plan for the occupation of Gaza. Influential actors, many of whom contribute to the insider journal Foreign Affairs , have continued to draw up schemes for the restoration or reinvention of a US-dominated multilateral order on a broader basis, with allies once again treated as allies while US power operates through rather than against global governance.

But the challenges to that old vision come from outside the United States as well as within. China and other so-called BRICs nations do not pose any fundamental anti-capitalist challenge to the Bretton Woods bodies. However, they do want a bigger say in how they operate, and China in particular is prepared to offer alternatives.

One example is its establishment of the Asian Infrastructure Investment Bank (AIIB) as a source of development finance in 2016. One study concludes that the AIIB “could unsettle the political influence the United States has enjoyed over developing countries through its leadership of the World Bank. An important set of countries may be parting ways with the World Bank and looking to a Chinese institution for leadership in the world of development.”

Summers bestrode the interlocking worlds of US and global governance like a colossus for decades, at a time when the United States became the world’s only superpower and its dominance seemed unchallengeable. His own tawdry fall from grace could serve as a metaphor for our changing times.

US imperialism is facing fundamental challenges , not just from the economic rise of China but also from worldwide popular revulsion at the genocide in Gaza in particular. Its ruling class is divided against itself, with the multilateralist wing represented by Summers on the defensive, and new financial storms are brewing. All of this comes against a backdrop of severe global indebtedness , both public and private, and an intensifying climate emergency.

Trump and Summers have much in common, with propensities for arrogance, bullying, sexism, and self-aggrandizement, not to mention a shared friendship with a notorious pedophile. But until recently, they represented different ideas of how best to advance US elite power and wealth. It is probable that neither of their approaches will prove sustainable (in Trump’s case) nor recoverable (in that of Summers) in the context of a crisis-ridden, increasingly multipolar world.

===

Andy Storey is a former lecturer in political economy at University College Dublin.

Windows 11 will ask consent before sharing personal files with AI after outrage

Hacker News
www.windowslatest.com
2025-12-17 00:27:58
Comments...
Original Article

Windows 11 AI ask consent to access personal files

Microsoft confirms that Windows 11 will ask for your consent before it allows an AI Agent to access your files stored in the six known folders, which include Desktop, Documents, Downloads, Music, Pictures, and Videos. You can also customize file access permissions for each agent.

This clarification comes after growing concerns around Microsoft’s push to bring AI agents deeper into Windows. Over the past few weeks, the company has been laying the groundwork for agent-based experiences that can interact with your files, apps, and system settings, even while openly admitting that AI models can misbehave , hallucinate, or create new security risks.

Until now, Microsoft hadn’t clearly explained how file access would work in practice, or whether users would have control over what these agents could see.

As first spotted by Windows Latest, on December 5, Microsoft quietly updated its Experimental Agentic Features support document to explain how consent, permissions, and agent connectors work in preview builds 26100.7344 and newer, finally confirming that AI agents cannot access your personal files by default and must explicitly ask for permission.

AI Agents in Windows 11 will need your permission to access files from known folders

A couple of weeks ago, Windows Latest pointed out how Microsoft wants to give AI access to your files and apps , even while admitting that such AI agents can misbehave and pose security risks.

“AI models still face functional limitations in terms of how they behave and occasionally may hallucinate and produce unexpected outputs”, says the company in their support document .

Experimental agentic features in Windows 11

Of course, a company confessing that its most promoted product introduces novel security risks cannot be taken lightly under any circumstances.

We noticed that although Microsoft insists that AI agents run under an agentic workspace, which is separate from the user workspace, and have limited permissions, Windows will still grant them access to your Desktop, Documents, Downloads, Music, Pictures, and Videos folders, which are collectively called the known folders .

This happened when you enabled the “Experimental Agentic features” toggle in Settings > System > AI components. Earlier, enabling the above toggle was supposed to grant access to these folders to all AI agents.

Windows 11 Agent Workspace
Image Courtesy: WindowsLatest.com

The company hadn’t made it clear how the agents could access these folders and whether or not we would be able to manage access.

However, Microsoft was quick to respond with an update to the support document after Windows Latest reached out for statements. Microsoft says it’s adding a clear consent step for AI agents. Even if you turn on Experimental agentic features, an agent doesn’t automatically get to read your files.

Copilot requesting personal folders access on Windows 11

You can also give separate permissions for individual agents, like Copilot, Researcher, or Analyst, to these folders collectively.

Yes, it means that while you can give per-agent access to the known folders, you cannot choose which of the six folders an AI agent can have access to. It’s either all of them or none of them.

I would prefer it if the Researcher and Analyst agents had all-time access to my Documents folder, while Copilot has to ask me every time if it needs access to any of my personal folders. But that’s not the case here.

Invoking agent from Ask Copilot in Taskbar
Invoking agent from Ask Copilot in Taskbar. Credit: Microsoft

That being said, you can still choose if the AI agent can get unlimited access at all times, or just allow access once, or no access at all. If an AI agent, like Copilot, needs to get hold of your files to complete a task, you’ll get a pop-up from which you can choose “Always allow”, “Allow once”, or “Not now”.

These options are only available for systems with preview builds 26100.7344 and above for 24H2, 26200.7344 and above for 25H2.

AI Agents get a dedicated Settings page in Windows 11

Each agent you have in Windows now gets its own Settings page from where you can manage its permission to access your files. In the screenshot below, you can change permissions to Connectors in Copilot, like OneDrive and Google Drive integration .

Windows 11 Agentic AI settings

The other “Connectors” just below Files and Connectors are, in fact, Agent Connectors, which are powered by Model Context Protocol (MCP) and are standardized bridges that allow AI agents to interact with apps in Windows. Microsoft is currently testing this with its push to bring AI Agents to the taskbar .

In the screenshot provided by Microsoft, you can also see two Agent Connectors, which let the Agent use the File Explorer app and System Settings app. You can set individual permissions for each of these, which means you can either allow AI agents to use these apps at all times, only once when you allow, or never at all.

To access these settings, go to the Settings app, select System > AI Components > Agents .

You’ll see the list of Agents available on your PC’s Windows OS. Select the agent and customize what these agents can access on your PC.

In the case of Files, Microsoft gives you three options. The Allow Always option gives the agent access to the six known folders whenever it has to. Selecting the Ask every time option will make Windows show you a prompt to give permission to share files in these folders when the agent needs them.

Of course, the Not now option will make Windows deny the request of the agent to access the folders.

This is a solution to a problem that Microsoft created when it said that AI would have access to your files. Anyway, the ability to manage permissions is good enough for now.

That being said, Microsoft also says that “​​​​​​​ Agent accounts have access to any folders that all authenticated users have access to, e.g., public user profiles.”

If the folder permissions include groups like Users / Authenticated Users with read access, then an agent account could access it.

Security properties in File Explorer

If the folder is locked to your user account (plus SYSTEM/Admins), then the agent account won’t have access unless Windows explicitly grants it via the known-folder consent flow.

Note that Microsoft has no word on when AI will be able to stop hallucinating or avoid novel security issues like cross-prompt injection (XPIA).

Interestingly, Microsoft made it a point to post in X that AI in Windows 11 will empower people “securely”, even as malware risks are unavoidable.

vm.overcommit_memory=2 is always the right setting

Lobsters
ariadne.space
2025-12-17 00:26:20
Comments...
Original Article

The Linux kernel has a feature where you can tune the behavior of memory allocations: the vm.overcommit_memory sysctl. When overcommit is enabled (sadly, this is the default), the kernel will typically return a mapping when brk(2) or mmap(2) is called to increase a program’s heap size, regardless of whether or not memory is available. Sounds good, right?

Not really. While overcommit is convenient for application developers, it fundamentally changes the contract of memory allocation: a successful allocation no longer represents an atomic acquisition of a real resource. Instead, the returned mapping serves as a deferred promise , which will only be fulfilled by the page fault handler if and when the memory is first accessed. This is an important distinction, as it means overcommit effectively replaces a fail-fast transactional allocation model with a best-effort one where failures are only caught after the fact rather than at the point of allocation.

To understand how this deferral works in practice, let’s consider what happens when a program calls malloc(3) to get a new memory allocation. At a high level, the allocator calls brk(2) or mmap(2) to request additional virtual address space from the kernel, which is represented by virtual memory area objects, also known as VMAs.

On a system where overcommit is disabled, the kernel ensures that enough backing memory is available to satisfy the request before allowing the allocation to succeed. In contrast, when overcommit is enabled, the kernel simply allocates a VMA object without guaranteeing that backing memory is available: the mapping succeeds immediately, even though it is not known whether the request can ultimately be satisfied.

The decoupling of success from backing memory availability makes allocation failures impossible to handle correctly. Programs have no other option but to assume the allocation has succeeded before the kernel has actually determined whether the request can be fulfilled. Disabling overcommit solves this problem by restoring admission control at allocation time, ensuring that allocations either fail immediately or succeed with a guarantee of backing memory.

Failure locality is important for debugging

When allocations fail fast, they are dramatically easier to debug, as the failure is synchronous with the request. When a program crashes due to an allocation failure, the entire context of that allocation is preserved: the requested allocation size, the subsystem making the allocation and the underlying operation that required it are already known.

With overcommit, this locality is lost by design. Allocations appear to succeed and the program proceeds under the assumption that the memory is available. When the allocation is eventually accessed, the kernel typically responds by invoking the OOM killer and terminating the process outright. From the program’s perspective, there is no allocation failure to handle, only a SIGKILL . From the operator’s perspective, there is no stack trace pointing to the failure. There are only post-mortem logs which often fail to paint a clear picture of what happened.

Would you rather debug a crash at the allocation site or reconstruct an outage caused by an asynchronous OOM kill? Overcommit doesn’t make allocation failure recoverable. It makes it unreportable.

Dishonorable mention: Redis

So why am I writing about this, anyway? The cost of overcommit isn’t just technical, it also represents bad engineering culture: shifting responsibility for correctness away from application developers and onto the kernel. As an example, when you start Redis with overcommit disabled, it prints a scary warning that you should re-enable it:

WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328 . To fix this issue add ‘vm.overcommit_memory = 1’ to /etc/sysctl.conf and then reboot or run the command ‘sysctl vm.overcommit_memory=1’ for this to take effect.

No. Code that requires overcommit to function correctly is failing to handle memory allocation errors correctly . The answer is not to print a warning that overcommit is disabled, but rather to surface low memory conditions explicitly so the system administrator can understand and resolve them.

Nurses Are the Best of Us. Trump’s Republican Party Should Take Notes.

Portside
portside.org
2025-12-17 00:26:14
Nurses Are the Best of Us. Trump’s Republican Party Should Take Notes. Judy Tue, 12/16/2025 - 19:26 ...
Original Article
Nurses Are the Best of Us. Trump’s Republican Party Should Take Notes. Published

Southfield, Michigan, Nurses rally outside Corewell Health during their fight for a union contract. Corewell is the largest healthcare system in Michigan. Its 10,000 nurses voted to join the Teamsters in late 2024 and are fighting for their first contract | Jim West/UCG/Universal Images Group via Getty Images

Apart from his “concepts of a plan,” it’s clear that Donald Trump doesn’t know much about healthcare . But there is one cardinal rule: don’t mess with nurses. After all, these are the folks who keep our healthcare system alive. My mother and grandmother are both nurses. They work brutal hours under nonstop pressure, juggling complex cases, emotional trauma, and physical exhaustion, while still showing up every day with the skill, compassion, and steady judgment required. As someone who’s led two of Michigan’s largest health departments, I know that if we want stronger hospitals, better patient outcomes, and a reliable healthcare workforce, we have to invest in our nurses and their education.

But Trump’s Department of Education decided to move us in exactly the opposite direction. Under rules buried deep in his “Big Beautiful Bill,” only certain graduate programs qualify as “professional degrees” eligible for higher loan caps, up to $50,000 a year or $200,000 total. And unbelievably, graduate nursing programs were excluded from that list of programs.

Our federal government wants to make it harder for nurses to step into the roles our healthcare system desperately needs to fill? Yes, you’re reading that right. This not only is a slap in the face to nurses everywhere, it leaves Americans with less options and safety in the care we can receive. As a doctor, I know our system is nothing without the care nurses provide. These continued attacks on Medicare and now on nurses from the White House are taking our broken system to the brink of failure, straining our country’s staffing crisis. This will hit rural hospitals hardest, where nurse practitioners are already providing so much primary care to patients.

I can’t think of a career more worthy of a “professional” designation than nursing, the most honest and trusted profession in America. President Trump has messed with the wrong folks.

Your circumstances shouldn’t hold you back from being able to pursue the kind of career and education you deserve. Federal student loans are one of the most effective tools we have to recruit talented folks into the nursing profession and make sure they can keep growing in their careers. When nurses can afford to become NPs, midwives, specialists, and educators, hospitals stay safely staffed and patients get the care they deserve.

Here in Michigan, we’re facing a projected 19% shortage of nurses by 2037. It’s not hard to understand why. Across the state, nurses are facing increasingly brutal working conditions as our healthcare systems consolidate, and the CEOs at the top put profits over patients. In the past few months, I’ve joined striking nurses in Mount Clemens, Rochester, and Grand Blanc who are all calling for safer staffing. And I can’t think of a career more worthy of a “professional” designation than nursing, the most honest and trusted profession in America. President Trump has messed with the wrong folks.

Without nurses, we are all worse off. We know you can’t strengthen the healthcare workforce by choking off the pathway to advanced training. And you cannot improve patient care while putting up new barriers for the very people who provide it.

Make no mistake, this is straight from the Project 2025 playbook. We knew they wanted to defund female-dominated professions (about 90 percent of nurses are women), come for working class Americans, and make education and healthcare even less accessible.

These loans aren’t a luxury. They’re how working nurses, the backbone of our hospitals, move into the advanced roles our health system depends on. The cost of attendance for nurses pursuing graduate degrees on average is over $30,000 per year, which exceeds the proposed annual cap of $20,500 per year. Without accessible loans, we lose future providers to burnout, stalled careers, and financial barriers that shut out entire communities.

We need loan programs that open doors, not close them.

===

Dr. Abdul El-Sayed is running for US Senate in Michigan. He ran two of the state’s largest health departments and wrote the book, Medicare for All: A Citizen's Guide .

WikiFlix shows us what Netflix would have been like 100 years ago

Hacker News
wikiflix.toolforge.org
2025-12-17 00:20:13
Comments...

Donald Trump’s Remarks on the Death of Rob Reiner Are Next-Level Degradation

Portside
portside.org
2025-12-17 00:12:06
Donald Trump’s Remarks on the Death of Rob Reiner Are Next-Level Degradation Judy Tue, 12/16/2025 - 19:12 ...
Original Article

Samuel Corum / Sipa / Bloomberg / Getty

Have you ever in your life encountered a character as wretched as Donald Trump ? For many people, this was a question asked and definitively answered twenty years ago, when Trump was still a real-estate vulgarian shilling his brand on Howard Stern’s radio show and agreeing with the host’s assessment that his daughter Ivanka was “a piece of ass” and describing how he could “get away with” going backstage at the Miss Universe pageant to see the contestants naked.

Or, perhaps, his character came clear a decade later, during his first run for the Presidency, when he said of John McCain , who spent more than five years being tortured in a North Vietnamese prison, “He’s not a war hero. He’s a war hero because he was captured. I like people that weren’t captured.” This was from a man who avoided the war with four student deferments and a medical deferment for bone spurs in his heel. Larry Braunstein, a podiatrist in Jamaica, Queens, who provided Trump with this timely diagnosis, in the fall of 1968, rented his office from Fred Trump, Donald’s father. One of the late doctor’s daughters told the Times , “I know it was a favor.”

One day, a historian will win a contract to assemble the collected quotations of the forty-fifth and forty-seventh President—all the press-room rants, the Oval Office put-downs, the 3 A.M. Truth Social fever dreams. The early chapters will include: “Blood coming out of her—wherever.” “Horseface.” “Fat pig.” “Suckers.” “Losers.” “Enemies of the people.” “Pocahontas.” And then the volume will move on to “Piggy.” “Things happen.” And so on.

After a decade of constant presence on the political stage, Trump no longer seems capable of shocking anyone with the brutality of his language or the heedlessness of his behavior. His supporters continue to excuse his insouciant cruelty as “Trump being Trump,” proof of his authenticity. (The antisemitism of Nick Fuentes , Tucker Carlson , and a gaggle of group-chatting young Republican leaders is, similarly, included in the “big tent” of MAGA rhetoric.) Now, when a friend begins a conversation with “Did you hear what Trump said today?,” you do your best to dodge the subject. What’s the point? And yet the President really did seem to break through to a new level of degradation this week.

This past weekend brought a terrible and rapid succession of violent events. On Saturday afternoon, in Providence, an unidentified gunman on the Brown University campus shot and killed two students and wounded nine others in the midst of exam period. The killer has yet to be found. On Sunday, in Archer Park, near Bondi Beach, in Sydney, Australia, a father-and-son team, both dressed in black and heavily armed, reportedly took aim at a crowd of Jewish men, women, and children who were celebrating the first night of Hanukkah. At least fifteen people were killed, including an eighty-seven-year-old Holocaust survivor and a ten-year-old girl. The massacre was the latest in a long series of antisemitic incidents in Australia—and beyond.

Finally, on Sunday night, came the news that the actor and filmmaker Rob Reiner and his wife, Michele Singer Reiner, had been found dead in their home. Their bodies were discovered by their daughter Romy. Los Angeles police arrested their son, the thirty-two-year-old Nick Reiner. According to press reports, the investigation had focussed on him immediately not only because of his history of drug abuse but also because he had been behaving erratically the night before, in his parents’ presence, at a holiday party at the home of Conan O’Brien. Nick Reiner is being held, without bail, in Los Angeles County jail.

There was something about these three events that came in such rapid succession that it savaged the spirit—the yet-again regularity of American mass shootings, this time in Providence; the stark Jew hatred behind the slaughter in Australia; the sheer sadness of losing such a beloved and decent figure in the popular culture, and his wife, purportedly at the hands of their troubled son. It would be naïve to think that any leader, any clergy, could ease all that pain with a gesture or a speech. Barack Obama speaking and singing “Amazing Grace” from the pulpit in Charleston, South Carolina, or Robert F. Kennedy speaking in Indianapolis on the night of the assassination of Martin Luther King, Jr.—that kind of moral eloquence is somehow beyond our contemporary imaginations and expectations. What you would not expect is for a President of the United States to make matters even worse than they were. But, of course, he did. “A very sad thing happened last night in Hollywood,” Trump wrote, on Truth Social, on Monday. He went on

Rob Reiner, a tortured and struggling, but once very talented movie director and comedy star, has passed away, together with his wife, Michele, reportedly due to the anger he caused others through his massive, unyielding, and incurable affliction with a mind crippling disease known as TRUMP DERANGEMENT SYNDROME, sometimes referred to as TDS.

He was known to have driven people CRAZY by his raging obsession of President Donald J. Trump, with his obvious paranoia reaching new heights as the Trump Administration surpassed all goals and expectations of greatness, and with the Golden Age of America upon us, perhaps like never before. May Rob and Michele rest in peace!

There is a lot to unpack here, from the shaky grammar to the decorous use of “passed away” to the all-caps diagnosis to the hideously gleeful sign-off: “rest in peace!” Future Trump scholars will sort through the details with the necessary deliberation. But it requires no deep thinking to assess Trump’s meaning. As if to assure the country that this was no passing case of morning dyspepsia, he declared, at a press conference, later in the day (using the kingly third-person approach) that Reiner “was a deranged person, as far as Trump is concerned.”

In the wake of the shocking death of Charlie Kirk , in September, there were many in the President’s circle who were quick to insist on the proper language of tragedy and mourning, and to ostracize those who failed to use it. As a citizen and an ardent liberal, Reiner was a harsh critic of the President; nor did his politics even remotely align with those of Charlie Kirk. Yet, when Reiner was asked about Kirk’s murder, he called it “an absolute horror,” and told Piers Morgan, “That should never happen to anybody. I don’t care what your political beliefs are.” And, when Erika Kirk, Charlie’s widow, delivered a speech of forgiveness at her husband’s memorial service in Arizona, Reiner was moved. “What she said, to me, was beautiful,” he said. “She forgave his assassin, and I think that is admirable.”

Remember what the President said by way of reply to Erika Kirk’s gesture of Christian love? “I hate my opponent, and I don’t want the best for them.” And he said this in a eulogy. And so it is worth asking, do you know anyone quite as malevolent? At your place of work? On your campus? A colleague? A teacher? Much less someone whose impulses and furies in no small measure dictate the direction, fate, and temper of the country? Have you ever in your life encountered a character as wretched as Donald Trump? ♦

===

David Remnick has been the editor of The New Yorker since 1998 and a staff writer since 1992. He is the author of seven books; the most recent is “ Holding the Note ,” a collection of his profiles of musicians.

James Cameron’s Instructions to Theater Projectionists Regarding ‘Avatar 3: Fire and Ash’

Daring Fireball
x.com
2025-12-17 00:05:28
The letter is typeset in Papyrus, the typeface for which James Cameron’s affection inspired not one but two classic SNL shorts starring Ryan Gosling — which Cameron has a good sense of humor about. Terrence Malick’s letter accompanying Tree of Life in 2011 was plainly and humbly set in Helvetica. D...

The new ChatGPT Images is here

Simon Willison
simonwillison.net
2025-12-16 23:59:22
The new ChatGPT Images is here OpenAI shipped an update to their ChatGPT Images feature - the feature that gained them 100 million new users in a week when they first launched it back in March, but has since been eclipsed by Google's Nano Banana and then further by Nana Banana Pro in November. The f...
Original Article

The new ChatGPT Images is here . OpenAI shipped an update to their ChatGPT Images feature - the feature that gained them 100 million new users in a week when they first launched it back in March, but has since been eclipsed by Google's Nano Banana and then further by Nana Banana Pro in November .

The focus for the new ChatGPT Images is speed and instruction following:

It makes precise edits while keeping details intact, and generates images up to 4x faster

It's also a little cheaper: OpenAI say that the new gpt-image-1.5 API model makes image input and output "20% cheaper in GPT Image 1.5 as compared to GPT Image 1".

I tried a new test prompt against a photo I took of Natalie's ceramic stand at the farmers market a few weeks ago:

Add two kakapos inspecting the pots

Outdoor craft market booth displaying handmade ceramics and jewelry on a navy tablecloth with "NATBAT CREATIONS CALIFORNIA USA" logo. Items include colorful glazed ceramic cups in blue, orange, and black; decorative bowls including a rainbow-striped piece; jewelry pendants and earrings on wooden display stands; ceramic plant markers in various colors labeled "Artichoke", "Cilantro", "Chili", "Oregano", "Potato", "Pumpkin", "Sage".

Here's the result from the new ChatGPT Images model:

Same craft market booth as previous image, now with two large olive-green Kākāpō parrots perched on the table among the ceramics, one investigating the blue glazed cups and the other examining an orange cup.

And here's what I got from Nano Banana Pro:

Same craft market booth with two Kākāpō now in different positions: one remains center-table peering into the ceramic cups near the rainbow pot, while the second has moved to the right edge of the table near the plant markers, appearing to examine or possibly chew on items at the table's corner. They are both a little smaller than in the first image.

The ChatGPT Kākāpō are a little chonkier, which I think counts as a win.

I was a little less impressed by the result I got for an infographic from the prompt "Infographic explaining how the Datasette open source project works" followed by "Run some extensive searches and gather a bunch of relevant information and then try again" ( transcript ):

Infographic titled "HOW DATASETTE WORKS" with subtitle "THE OPEN SOURCE DATA PLATFORM" showing a four-step workflow. STEP 1 (orange): "LOAD YOUR DATA" - "CSV, JSON, XLSX, SQLite, PostgreSQL, etc." with icons of file types flowing into a laptop. Below: "IMPORT DATASETS - Turn your structured data into SQLite databases and .db files." with checkmarks for "Datasette Desktop App for local deployment", "CLI tool for command-line imports", "Automatic CSV import tool". STEP 2 (green): "PUBLISH & DEPLOY" - "HOST DATASETS ONLINE" with cloud and server icons labeled "DEPLOY". Below: "SHARE ONLINE - Deploy your Datasette instance to a public server." with checkmarks for "Datasette Cloud - Free hosting service", "Deploy anywhere via plugins", "Configurable API tools". STEP 3 (purple): "EXPLORE & QUERY" - "BROWSE, SEARCH & VISUALIZE" with database and browser window icons. Below: "SQL QUERIES & SEARCH - Browse, filter, search, and visualize your data with an interactive web interface." with checkmarks for "Perform SQL queries directly from the browser", "Filter, sort, and facet data", "Generate custom visualizations and charts". STEP 4 (red): "BUILD & EXTEND" - "PLUGINS, APIS & INTEGRATIONS" with gear and wrench icons labeled "API". Below: "CUSTOMIZE & DEVELOP" with bullets "Develop custom plugins for added functionality", "Access JSON API for programmatic queries", "Embed and integrate Datasette into other applications". Bottom banner shows four features: "OPEN DATA PLATFORM - Widely used for visualizing, sharing and building applications with SQLite backed data", "EXTENSIBLE PLUGINS - 100+ plugins available, inc uding chaps, charts authentication, and more", "ACCESS CONTROL - Granular permissions for controlling who s an access and interact with your data", "OPEN SOURCE PROJECT - Actively developed open source project with a vibrant community of contributors".

See my Nano Banana Pro post for comparison.

Both models are clearly now usable for text-heavy graphics though, which makes them far more useful than previous generations of this technology.

s3-credentials 0.17

Simon Willison
simonwillison.net
2025-12-16 23:40:31
s3-credentials 0.17 New release of my s3-credentials CLI tool for managing credentials needed to access just one S3 bucket. Here are the release notes in full: New commands get-bucket-policy and set-bucket-policy. #91 New commands get-public-access-block and set-public-access-block. #92 New locals...
Original Article

s3-credentials 0.17 . New release of my s3-credentials CLI tool for managing credentials needed to access just one S3 bucket. Here are the release notes in full:

  • New commands get-bucket-policy and set-bucket-policy . #91
  • New commands get-public-access-block and set-public-access-block . #92
  • New localserver command for starting a web server that makes time limited credentials accessible via a JSON API. #93

That s3-credentials localserver command ( documented here ) is a little obscure, but I found myself wanting something like that to help me test out a new feature I'm building to help create temporary Litestream credentials using Amazon STS.

Most of that new feature was built by Claude Code from the following starting prompt:

Add a feature s3-credentials localserver which starts a localhost weberver running (using the Python standard library stuff) on port 8094 by default but -p/--port can set a different port and otherwise takes an option that names a bucket and then takes the same options for read--write/read-only etc as other commands. It also takes a required --refresh-interval option which can be set as 5m or 10h or 30s. All this thing does is reply on / to a GET request with the IAM expiring credentials that allow access to that bucket with that policy for that specified amount of time. It caches internally the credentials it generates and will return the exact same data up until they expire (it also tracks expected expiry time) after which it will generate new credentials (avoiding dog pile effects if multiple requests ask at the same time) and return and cache those instead.

ty: An extremely fast Python type checker and LSP

Simon Willison
simonwillison.net
2025-12-16 23:35:33
ty: An extremely fast Python type checker and LSP The team at Astral have been working on this for quite a long time, and are finally releasing the first beta. They have some big performance claims: Without caching, ty is consistently between 10x and 60x faster than mypy and Pyright. When run in a...
Original Article

ty: An extremely fast Python type checker and LSP ( via ) The team at Astral have been working on this for quite a long time, and are finally releasing the first beta. They have some big performance claims:

Without caching, ty is consistently between 10x and 60x faster than mypy and Pyright. When run in an editor, the gap is even more dramatic. As an example, after editing a load-bearing file in the PyTorch repository, ty recomputes diagnostics in 4.7ms: 80x faster than Pyright (386ms) and 500x faster than Pyrefly (2.38 seconds). ty is very fast!

The easiest way to try it out is via uvx :

cd my-python-project/
uvx ty check

I tried it against sqlite-utils and it turns out I have quite a lot of work to do!

Astral also released a new VS Code extension adding ty-powered language server features like go to definition. I'm still getting my head around how this works and what it can do.

Americans overestimate how many social media users post harmful content

Hacker News
academic.oup.com
2025-12-16 23:28:39
Comments...

More than 100 rally against data centers at Michigan Capitol

Hacker News
www.lansingstatejournal.com
2025-12-16 23:27:10
Comments...
Original Article

Updated Dec. 16, 2025, 5:54 p.m. ET

  • Over 100 people rallied at the Michigan state Capitol to protest the development of data centers.
  • Concerns raised by protestors included potential electricity rate hikes, water usage, and a lack of transparency.
  • Michigan Attorney General Dana Nessel criticized a massive proposed project in Saline Township involving OpenAI and Oracle.

LANSING — More than 100 people joined in chants against data centers, braving the cold to get their point across at the state Capitol on Dec. 16.

"No secret deals!" they shouted. "No secret deals!"

They held signs noting dangers to water and potential electricity rate increases because of data centers being proposed across the state — from a 24-megawatt, less-than-an-acre facility being proposed for downtown Lansing to a 1.4-gigawatt massive data center on 250 acres causing an uproar in Saline Township.

They listened to Michigan Attorney General Dana Nessel criticizing the lack of transparency with DTE Energy, the utility that's associated with the Saline Township proposal, and legislators who protested tax breaks for data center projects.

The Saline Township project involves OpenAI — the creator of the popular artificial intelligence product ChatGPT — software giant Oracle and Related Digital, a subsidiary of New York-based Related Companies. Nessel called it the biggest data center for the state of Michigan and one of the biggest for America.

"We're talking about 1.4 gigawatts, which is, of course, enough to provide energy to a city of a million people," Nessel said. "I think we should be taking this extremely seriously, don't you? Do you guys trust DTE? Do you trust Open AI? Do we trust Oracle to look out for our best interests here in Michigan?"

To each question, members of the crowd shouted, "No!"

A Facebook group, "Michiganders Against Data Centers," organized the rally that drew residents from as far as Detroit to the east and Lowell and Kalamazoo to the west.

Data center plans that would provide the infrastructure for today's digital world and are touted as a key component for artificial intelligence already have found approval in Lyon Township and Southfield .

Demonstrators, including Seth Bernard, of Lake City, rally Tuesday, Dec. 16, 2025, during the Michiganders Against Data Centers protest at the state Capitol in Lansing.

The Lansing City Council is expected to vote early in the new year on United Kingdom-based Deep Green's conditional rezoning request and a sale of city-owned parcels mainly functioning as parking lots to build a two-story, 25,000-square-foot, 24-megawatt data center along Kalamazoo Street, between Cedar and Larch streets.

Patrick and Pam Lind of the Mason area were in the crowd, holding a sign that protested data centers being potentially placed in Mason and Vevay Township.

"We're trying to get in front of this to stop it," Patrick Lind said.

He had hoped to see more people at the rally, but his wife was thankful to see the diverse crowd, which included people from various backgrounds.

"They are reflecting what the Michigan citizens are feeling about our natural resources," Pam Lind said, emphasizing Michigan's Great Lakes and fresh water. "We don't like to see it sold out. We don't want to see it polluted. We don't want to see the water levels dropping. We care about our people. We care about their health and their mental well-being. We care about our rural and our farmlands. That's Pure Michigan."

Among the legislators in attendance, state Rep. Reggie Miller, D-Van Buren Township, spoke out against a "gold rush mentality" of the data center developers and Rep. James DeSana, R-Carleton, spoke out against tax breaks for data centers and their push to move into Michigan.

Demonstrators protest Tuesday, Dec. 16, 2025, during the Michiganders Against Data Centers rally at the state Capitol in Lansing.

"We need the entire state to stand up," DeSana said. "These could come to your area. You think you're safe today because you don't have a data center next to you. Just wait. They're coming."

East Lansing resident Nichole Keway Biber also attended the rally.

She said data center developers don't want people to ask questions about artificial intelligence's repercussions on the environment, jobs, mental health and children's cognitive development.

"They're trying to push it on us as something we need rather than the reality that we need our lands for food," she said. "We need our water to get cleaner, not be filled with even more chemicals."

Tim Bruneau of Saline Township lives less than two miles from the proposed data center site.

"There's no demonstrated need for a data center in Saline Township or one of the other 23 or 24 that we know of at this time affecting communities," Bruneau said. "It's exploitation dressed up as innovation. This is not just a development proposal. It is, by every meaningful definition, a war on our way of life."

Contact editor Susan Vela at svela@lsj.com or 248-873-7044. Follow her on Twitter @susanvela .

UK insists US tech deal not dead as Trump threatens penalties against European firms

Guardian
www.theguardian.com
2025-12-16 23:20:32
Keir Starmer’s office claims UK still in ‘active conversations’ about deal for tech industries in both countries to cooperate Downing Street insists the $40bn Tech Prosperity Deal between the US and UK that is on hold is not permanently stalled. The BBC reported on Tuesday evening that the prime min...
Original Article

Downing Street insists the $40bn Tech Prosperity Deal between the US and UK that is on hold is not permanently stalled. The BBC reported on Tuesday evening that the prime minister’s office claimed that the UK remains in “active conversations with US counterparts at all levels of government” about the wide-ranging deal for the technology industries in both countries to cooperate.

The agreement, previously billed as historic, was paused after the US accused the UK of failing to lower trade barriers, including a digital services tax on US tech companies and food safety rules that limit the export of some agricultural products. The New York Times first reported British confirmation that negotiations had stalled.

“We look forward to resuming work on this partnership as quickly as possible,” a Downing Street spokesperson said in a statement. She added that the UK government is committed to ensuring a “bond” with the US “and working together to help shape the emerging technologies of the future”.

The White House did not immediately respond to a request for comment.

Tuesday’s developments come as relations between the US and the EU are likewise chilling. The Trump administration threatened European tech firms on Tuesday with economic penalties if the EU refused to roll back what it called “discriminatory actions”. The Office of the US Trade Representative accused the EU and some member states of “discriminatory and harassing lawsuits, taxes, fines and directives against U.S. services”.

The Trade Representative’s office said in a post on Twitter/X that these companies could face fees and restrictions on foreign services. The bureau singled out European companies, including Accenture, DHL, Spotify and Siemens as being able to “operate freely in the United States for decades, benefitting from access to our market and consumers on a level playing field.

“If the E.U. and E.U. Member States insist on continuing to restrict, limit, and deter the competitiveness of U.S. service providers through discriminatory means, the United States will have no choice but to begin using every tool at its disposal to counter these unreasonable measures,” the Office of the U.S. Trade Representative said on X.

Thomas Regnier, a spokesperson for the European Commission, responded by stressing that their rules “apply equally and fairly to all companies” operating in the region, according to the New York Times . “We will continue to enforce our rules fairly, and without discrimination,” he said.

The retaliation by the US follows a $140m fine slapped on Elon Musk’s X social media platform for violating transparency rules under the Digital Services Act. EU regulators took issue with the “deceptive design of X’s ‘blue checkmark’,” “lack of transparency of X’s ads repository” and “failure to provide researchers access to public data”. The EU has proven much more willing than the US to regulate, investigate and penalize tech giants, a point of contention with the Trump administration.

Rob Reiner Obituary

Portside
portside.org
2025-12-16 23:12:52
Rob Reiner Obituary Judy Tue, 12/16/2025 - 18:12 ...
Original Article

Rob Reiner, who has died aged 78, was an actor, director and producer whose career path went from playing Mike “Meathead” Stivic, son-in-law of Archie Bunker in Norman Lear ’s television sitcom All in the Family in the 1970s, to directing a remarkable run of hit films between This Is Spinal Tap in 1984 and A Few Good Men in 1992 that included The Princess Bride (1987), When Harry Met Sally (1989) and Misery (1990).

He also co-founded the production company Castle Rock Entertainment, which made In the Line of Fire, City Slickers and Lone Star, as well as the Stephen King adaptations The Shawshank Redemption, Dolores Claiborne and The Green Mile, and the TV comedy Seinfeld. After selling Castle Rock to Turner Broadcasting in 1993, Reiner undertook more activism and made smaller movies. “I came into this business to express myself and tell stories,” he told the Guardian in 2018, “not just to churn out a product.”

Reiner’s career in many ways echoed that of his father, Carl Reiner – and, like Carl, he often drew on his own life in his work. Carl was a successful comedian and writer, a product of Sid Caesar ’s Your Show of Shows; Rob’s mother, Estelle (nee Lebost), was an actor and jazz singer. Rob was born in the Bronx, New York, and grew up around such people as Mel Brooks, with whom Carl made the hit comedy record The 2,000 Year Old Man. The family moved to the affluent suburb of New Rochelle, which provided the material for Carl to create The Dick Van Dyke Show, with Van Dyke playing a comedy writer living in the suburbs with his wife ( Mary Tyler Moore ) and kids.

Eventually the family moved to Los Angeles, where Rob made his TV debut with a small part in the series Manhunt when he was 14. He acted in his high-school drama class, and at his parents’ urging did summer theatre back east in the resorts of the Pocono mountains. At 19 he and Larry Bishop (son of the Rat Pack comic Joey ) were the opening act for the singer Carmen McRae at the Hungry I club, San Francisco, and, inspired by the comedian Mort Sahl , were part of a satirical improv group called the Committee.

Reiner had a small part in the fabulous comedy Where’s Poppa? (1970) and acted in numerous TV shows, including episodes of the military comedy Gomer Pyle, USMC, playing a beatnik, and That Girl, opposite Marlo Thomas. Meanwhile, he was writing liberal satire for The Smothers Brothers Comedy Hour (partnered with Steve Martin).

In 1971 he won the part of Meathead (Lear’s All in the Family was a US Version of the UK show Till Death Us Do Part, and the corresponding role in the BBC version was played by Tony Booth ) over Harrison Ford and Richard Dreyfuss, his high-school best friend. Playing the liberal punching bag for Carroll O’Connor ’s Archie, Reiner won two Emmys for best supporting actor in a comedy.

River Phoenix, left, and Will Wheaton in Stand By Me, 1986.

River Phoenix, left, and Will Wheaton in Stand By Me, 1986. Photograph: Allstar Picture Library Limited/Alamy

In 1971 he married Penny Marshall , who also progressed from comedy actor to director; they had been neighbours in the Bronx without knowing each other. He adopted Marshall’s daughter Tracy before the couple divorced in 1981.

Reiner’s first directing job was the TV movie Sonny Boy (1974). He left All in the Family in 1978, but made a couple of appearances in the spin-off series Archie Bunker’s Place. Then he began working on This Is Spinal Tap, the rock mockumentary in which he played the director Marty DiBergi (a parodying tip of the hat to Martin Scorsese), whose key scene about Nigel Tufnel’s amp “ going up to 11 ” has become a classic.

Stand By Me (1986), an adaptation of King’s novella The Body, is arguably his most personal work, a coming of age story that never puts a foot wrong. Reiner’s instinct for the truth in King’s non-horror writing began a long working relationship; King would option his work to Reiner for $1.

Reiner appreciated great writing. Nora Ephron based much of When Harry Met Sally on Reiner’s own difficulty dating after his divorce. He met his second wife, the photographer Michele Singer, on the film’s set. It was Reiner’s mother, too, who delivered the film’s zinger line (suggested by the star Billy Crystal) after Meg Ryan demonstrates faking an orgasm over lunch at Katz’s deli . “I’ll have what she’s having,” Estelle says, knowingly.

William Goldman adapted his own novel for The Princess Bride, which works because it takes its fantasy tale seriously, while wrongfooting the audience’s disbelief with comedy. Goldman also helped adapt Aaron Sorkin’s original play into A Few Good Men, which was nominated for the best picture Oscar and demonstrates the trademark Sorkin social liberalism laced with respect for institutes and fetishising of the military.

After Turner’s purchase of Castle Rock (along with its distribution arm New Line), in a deal worth hundreds of millions, Reiner’s public profile as a liberal activist and Democratic party mover rose. He co-founded the American Foundation for Equal Rights , which helped to overturn California’s state ban on gay marriage, and worked to supply more state and federal funding of child development. At one stage, his name was floated to run against Arnold Schwarzenegger for California’s governorship, but, he said: “I don’t want to be an elected official, I want to get things done.”

1989, WHEN HARRY MET SALLY...MEG RYAN Character(s): Sally Albright Film 'WHEN HARRY MET SALLY...' (1989) Directed By ROB REINER 12 July 1989

Meg Ryan in When Harry Met Sally, 1989. Photograph: Columbia Pictures/Allstar

His most popular later work was probably The Bucket List (2007), a comedy with Jack Nicholson and Morgan Freeman; the least was North (1994), a father/son coming of age drama. The Sorkin-scripted love story The American President (1995) was one of many politically themed films, which included two written by Joey Hartstone, the 2016 biopic LBJ and Shock and Awe (2017), detailing journalists’ struggles to report George W Bush’s 2003 Iraq war accurately, in which Reiner played an editor. Ghosts of Mississippi (1996) dealt with bringing the killers of the civil rights activist Medgar Evers to justice. His 2012 release, 8, filmed Dustin Lance Black’s original theatre production built from the transcripts of the court case against the law banning gay marriage.

Being Charlie (2015), which Reiner and his son Nick wrote together, fictionalised Nick’s struggles with addiction and rehab, and his parents’ reliance on expert help at the expense of mutual understanding. The father in the script is a movie star running for political office.

Reiner had a lifelong interest in the JFK assassination, and in 2023 he released a podcast, Who Killed JFK?, co-hosted with Soledad O’Brien, that purported to name the actual assassins, though it served better as an introduction for many listeners to the questions never solved by official accounts. His most recent film was the Spinal Tap sequel Spinal Tap II: The End Continues (2025).

Reiner and his wife were found dead at their home in Los Angeles in what the city’s police department described as “an apparent double homicide”. He is survived by their children, Romy, Nick and Jake, and by his daughter Tracy.

Robert Norman Reiner, director, producer, screenwriter and actor, born 6 March 1947; died 14 December 2025

===

Being free from billionaire and corporate ownership means the Guardian will never compromise our independence – but it also means we rely on support from readers who understand how essential it is to have news sources that are immune to intimidation from the powerful. We know our requests for support are not as welcome as our reporting, but without them, it’s simple: our reporting wouldn’t exist. Of course, we understand that some readers are not in a position to support us, and if that is you, we value your readership no less.

But if you are able, please support us today.

Cellik Android malware builds malicious versions from Google Play apps

Bleeping Computer
www.bleepingcomputer.com
2025-12-16 22:59:35
A new Android malware-as-a-service (MaaS) named Cellik is being advertised on underground cybercrime forums offering a robust set of capabilities that include the option to embed it in any app available on the Google Play Store. [...]...
Original Article

Cellik Android malware builds malicious versions from Google Play apps

A new Android malware-as-a-service (MaaS) named Cellik is being advertised on underground cybercrime forums offering a robust set of capabilities that include the option to embed it in any app available on the Google Play Store.

Specifically, attackers can select apps from Android's official app store and create trojanized versions that appear trustworthy and keep the real app's interface and functionality.

By providing the expected capabilities, Cellik infections can go unnoticed for a longer time. Additionally, the seller claims that bundling the malware this way may help bypass Play Protect, although this is unconfirmed.

Wiz

Mobile security firm iVerify discovered Cellik on underground forums where it is offered for $150/month or $900 for lifetime access.

Cellik capabilities

Cellik is a fully-fledged Android malware that can capture and stream the victim's screen in real time, intercept app notifications, browse the filesystem, exfiltrate files, wipe data, and communicate with the command-and-control server via an encrypted channel.

Live feed of victim's screen
Live feed of the victim's screen
Source: iVerify

The malware also features a hidden browser mode that attackers can use to access websites from the infected device using the victim's stored cookies.

An app injection system allows attackers to overlay fake login screens or inject malicious code into any app to steal the victim's account credentials.

The listed capabilities also include the option to inject payloads onto installed apps, which would make pinpointing the infection even more difficult, as long-trusted apps suddenly turn rogue.

Cellik's hidden browser mode
Cellik's hidden browser mode
Source: iVerify

The highlight, though, is the Play Store integration into Cellik's APK builder, which allows cybercriminals to browse the store for apps, select the ones they want, and create a malicious variant of them.

"The seller claims Cellik can bypass Google Play security features by wrapping its payload in trusted apps, essentially disabling Play Protect detection," explains iVerify .

"While Google Play Protect typically flags unknown or malicious apps, trojans hidden inside popular app packages might slip past automated reviews or device-level scanners."

BleepingComputer has contacted Google to ask if Cellik-bundled apps can indeed evade Play Protect, but a comment wasn't immediately available.

To stay safe, Android users should avoid sideloading APKs from dubious sites unless they trust the publisher, ensure Play Protect is active on the device, review app permissions, and monitor for unusual activity.

tines

Break down IAM silos like Bitpanda, KnowBe4, and PathAI

Broken IAM isn't just an IT problem - the impact ripples across your whole business.

This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

Poe the Poet

Simon Willison
simonwillison.net
2025-12-16 22:57:02
Poe the Poet I was looking for a way to specify additional commands in my pyproject.toml file to execute using uv. There's an enormous issue thread on this in the uv issue tracker (300+ comments dating back to August 2024) and from there I learned of several options including this one, Poe the Poet....
Original Article

Poe the Poet . I was looking for a way to specify additional commands in my pyproject.toml file to execute using uv . There's an enormous issue thread on this in the uv issue tracker (300+ comments dating back to August 2024) and from there I learned of several options including this one, Poe the Poet.

It's neat. I added it to my s3-credentials project just now and the following now works for running the live preview server for the documentation:

uv run poe livehtml

Here's the snippet of TOML I added to my pyproject.toml :

[dependency-groups]
test = [
    "pytest",
    "pytest-mock",
    "cogapp",
    "moto>=5.0.4",
]
docs = [
    "furo",
    "sphinx-autobuild",
    "myst-parser",
    "cogapp",
]
dev = [
    {include-group = "test"},
    {include-group = "docs"},
    "poethepoet>=0.38.0",
]

[tool.poe.tasks]
docs = "sphinx-build -M html docs docs/_build"
livehtml = "sphinx-autobuild -b html docs docs/_build"
cog = "cog -r docs/*.md"

Since poethepoet is in the dev= dependency group any time I run uv run ... it will be available in the environment.

Dafny: Verification-Aware Programming Language

Hacker News
dafny.org
2025-12-16 22:50:59
Comments...
Original Article

Dafny is a verification-aware programming language that has native support for recording specifications and is equipped with a static program verifier. By blending sophisticated automated reasoning with familiar programming idioms and tools, Dafny empowers developers to write provably correct code (w.r.t. specifications). It also compiles Dafny code to familiar development environments such as C#, Java, JavaScript, Go and Python (with more to come) so Dafny can integrate with your existing workflow. Dafny makes rigorous verification an integral part of development, thus reducing costly late-stage bugs that may be missed by testing.

In addition to a verification engine to check implementation against specifications, the Dafny ecosystem includes several compilers, plugins for common software development IDEs, a LSP-based Language Server, a code formatter, a reference manual, tutorials, power user tips, books, the experiences of professors teaching Dafny, and the accumulating expertise of industrial projects using Dafny.

Dafny has support for common programming concepts such as

Dafny also offers an extensive toolbox for mathematical proofs about software, including

A snippet of code shown in the VSCode IDE showing an implementation of the Dutch national flag problem written in Dafny.  IDE extensions are showing successes and failures in verification reported by the Dafny Language Server running in real time.
Dafny running in Visual Studio Code

I ported JustHTML from Python to JavaScript with Codex CLI and GPT-5.2 in hours

Hacker News
simonwillison.net
2025-12-16 22:48:56
Comments...
Original Article

15th December 2025

I wrote about JustHTML yesterday —Emil Stenström’s project to build a new standards compliant HTML5 parser in pure Python code using coding agents running against the comprehensive html5lib-tests testing library. Last night, purely out of curiosity, I decided to try porting JustHTML from Python to JavaScript with the least amount of effort possible, using Codex CLI and GPT-5.2. It worked beyond my expectations.

TL;DR

I built simonw/justjshtml , a dependency-free HTML5 parsing library in JavaScript which passes 9,200 tests from the html5lib-tests suite and imitates the API design of Emil’s JustHTML library.

It took two initial prompts and a few tiny follow-ups. GPT-5.2 running in Codex CLI ran uninterrupted for several hours, burned through 1,464,295 input tokens, 97,122,176 cached input tokens and 625,563 output tokens and ended up producing 9,000 lines of fully tested JavaScript across 43 commits.

Time elapsed from project idea to finished library: about 4 hours, during which I also bought and decorated a Christmas tree with family and watched the latest Knives Out movie.

Some background

One of the most important contributions of the HTML5 specification ten years ago was the way it precisely specified how invalid HTML should be parsed. The world is full of invalid documents and having a specification that covers those means browsers can treat them in the same way—there’s no more “undefined behavior” to worry about when building parsing software.

Unsurprisingly, those invalid parsing rules are pretty complex! The free online book Idiosyncrasies of the HTML parser by Simon Pieters is an excellent deep dive into this topic, in particular Chapter 3. The HTML parser .

The Python html5lib project started the html5lib-tests repository with a set of implementation-independent tests. These have since become the gold standard for interoperability testing of HTML5 parsers, and are used by projects such as Servo which used them to help build html5ever , a “high-performance browser-grade HTML5 parser” written in Rust.

Emil Stenström’s JustHTML project is a pure-Python implementation of an HTML5 parser that passes the full html5lib-tests suite. Emil spent a couple of months working on this as a side project, deliberately picking a problem with a comprehensive existing test suite to see how far he could get with coding agents.

At one point he had the agents rewrite it based on a close inspection of the Rust html5ever library. I don’t know how much of this was direct translation versus inspiration (here’s Emil’s commentary on that )—his project has 1,215 commits total so it appears to have included a huge amount of iteration, not just a straight port.

My project is a straight port. I instructed Codex CLI to build a JavaScript version of Emil’s Python code.

The process in detail

I started with a bit of mise en place. I checked out two repos and created an empty third directory for the new project:

cd ~/dev
git clone https://github.com/EmilStenstrom/justhtml
git clone https://github.com/html5lib/html5lib-tests
mkdir justjshtml
cd justjshtml

Then I started Codex CLI for GPT-5.2 like this:

That --yolo flag is a shortcut for --dangerously-bypass-approvals-and-sandbox , which is every bit as dangerous as it sounds.

My first prompt told Codex to inspect the existing code and use it to build a specification for the new JavaScript library:

We are going to create a JavaScript port of ~/dev/justhtml - an HTML parsing library that passes the full ~/dev/html5lib-tests test suite. It is going to have a similar API to the Python library but in JavaScript. It will have no dependencies other than raw JavaScript, hence it will work great in the browser and node.js and other environments. Start by reading ~/dev/justhtml and designing the user-facing API for the new library - create a spec.md containing your plan.

I reviewed the spec, which included a set of proposed milestones, and told it to add another:

Add an early step to the roadmap that involves an initial version that parses a simple example document that is valid and returns the right results. Then add and commit the spec.md file.

Here’s the resulting spec.md file . My request for that initial version became “Milestone 0.5” which looked like this:

Milestone 0.5 — End-to-end smoke parse (single valid document)

  • Implement the smallest end-to-end slice so the public API is real early:
    • new JustHTML("<html><head></head><body><p>Hello</p></body></html>") returns a tree with the expected tag structure and text nodes.
    • doc.toText() returns "Hello" and doc.errors is empty for this valid input.
  • Add scripts/smoke.js (no deps) that runs the example and asserts the expected structure/output.
  • Gate: node scripts/smoke.js passes.

Then I told it:

Implement Milestone 0.5

And off it went. The resulting code appeared to work so I said:

Configure GitHub Actions test.yml to run that on every commit, then commit and push

I ran git init and created a private GitHub repository for this project at this point, and set up the local directory to push to that remote.

Here’s that initial push . Then I told it:

OK do the rest, commit and push often

And that was almost it!

I set my laptop to not fall asleep and left it to its devices while we went off to buy a Christmas tree. The “commit and push often” meant I could monitor its progress on my phone by refreshing the commit log on GitHub .

I was running this against my $20/month ChatGPT Plus account, which has a five hour token allowance window for Codex CLI. That ran out at 6:35pm and Codex paused, so I waited until the reset point at 7:14pm and typed:

Keep going

At 9:30pm it declared itself done with the following summary message:

• What’s Done

  - html5lib-tests now run in CI and pass: tokenizer 6810/6810, tree 1770/1782
    (12 skipped: #script-on), serializer 230/230, encoding 82/83 (1 skipped:
    scripted) (.github/workflows/test.yml:1).
  - Public API expanded: stream() (src/stream.js:1), CSS selectors query()/
    matches() (src/selector.js:1), and toMarkdown() (src/markdown.js:1), all
    exported via src/index.js:1.
  - Added no-deps unit scripts for selectors/stream/markdown (scripts/run-
    selector-tests.js:1, scripts/run-stream-tests.js:1, scripts/run-markdown-
    tests.js:1) and wired them into CI.
  - Fixed TreeBuilder so <br> no longer closes <p> (src/treebuilder.js:647).

As a finishing touch, I had it add a playground interface so I could try out the new library in my browser. I prompted:

Add a playground.html in the top level folder which loads the necessary ES modules from ./src/... and implements the exact same functionality as seen on https://tools.simonwillison.net/justhtml but using the JavaScript library instead of Pyodide

It fetched my existing JustHTML playground page ( described here ) using curl and built a new playground.html file that loaded the new JavaScript code instead. This worked perfectly .

I enabled GitHub Pages for my still-private repo which meant I could access the new playground at this URL:

https://simonw.github.io/justjshtml/playground.html

Screenshot of JustJSHTML Playground web application. Header reads "JustJSHTML Playground" with subtitle "A dependency-free JavaScript HTML5 parser - GitHub". Below is a status bar showing "JavaScript Environment" with a green "Ready" badge. The main input area has "Paste HTML" and "Fetch from URL" buttons, with a text area containing HTML code: "<!DOCTYPE html> <html> <head> <title>Example Page</title> </head> <body> <header> <nav> <ul>". A "Playground Mode" section shows buttons for "CSS Selector Query", "Pretty Print HTML", "Tree Structure", "Stream Events", "Extract Text", and "To Markdown" (highlighted in purple). Below is a text field labeled "CSS Selector (optional - leave empty for whole document):" with placeholder "e.g., article, main, .content (or leave empty)" and a green "Convert to Markdown" button. The Output section has a teal header with "Whole document" badge and displays converted markdown: "Example Page" followed by "- [Home](/)" "- [About](/about)" "- [Contact](/contact)".

All it needed now was some documentation:

Add a comprehensive README with full usage instructions including attribution plus how this was built plus how to use in in HTML plus how to use it in Node.js

You can read the result here .

We are now at eight prompts total, running for just over four hours and I’ve decorated for Christmas and watched Wake Up Dead Man on Netflix.

According to Codex CLI:

Token usage: total=2,089,858 input=1,464,295 (+ 97,122,176 cached) output=625,563 (reasoning 437,010)

My llm-prices.com calculator estimates that at $29.41 if I was paying for those tokens at API prices, but they were included in my $20/month ChatGPT Plus subscription so the actual extra cost to me was zero.

What can we learn from this?

I’m sharing this project because I think it demonstrates a bunch of interesting things about the state of LLMs in December 2025.

  • Frontier LLMs really can perform complex, multi-hour tasks with hundreds of tool calls and minimal supervision. I used GPT-5.2 for this but I have no reason to believe that Claude Opus 4.5 or Gemini 3 Pro would not be able to achieve the same thing—the only reason I haven’t tried is that I don’t want to burn another 4 hours of time and several million tokens on more runs.
  • If you can reduce a problem to a robust test suite you can set a coding agent loop loose on it with a high degree of confidence that it will eventually succeed. I called this designing the agentic loop a few months ago. I think it’s the key skill to unlocking the potential of LLMs for complex tasks.
  • Porting entire open source libraries from one language to another via a coding agent works extremely well.
  • Code is so cheap it’s practically free. Code that works continues to carry a cost, but that cost has plummeted now that coding agents can check their work as they go.
  • We haven’t even begun to unpack the etiquette and ethics around this style of development. Is it responsible and appropriate to churn out a direct port of a library like this in a few hours while watching a movie? What would it take for code built like this to be trusted in production?

I’ll end with some open questions:

  • Does this library represent a legal violation of copyright of either the Rust library or the Python one?
  • Even if this is legal, is it ethical to build a library in this way?
  • Does this format of development hurt the open source ecosystem?
  • Can I even assert copyright over this, given how much of the work was produced by the LLM?
  • Is it responsible to publish software libraries built in this way?
  • How much better would this library be if an expert team hand crafted it over the course of several months?

GhostPoster attacks hide malicious JavaScript in Firefox addon logos

Bleeping Computer
www.bleepingcomputer.com
2025-12-16 22:17:46
A new campaign dubbed 'GhostPoster' is hiding JavaScript code in the image logo of malicious Firefox extensions counting more than 50,000 downloads, to monitor browser activity and plant a backdoor. [...]...
Original Article

GhostPoster attacks hide malicious JavaScript in Firefox addon logos

A new campaign dubbed 'GhostPoster' is hiding JavaScript code in the image logo of malicious Firefox extensions with more than 50,000 downloads, to monitor browser activity and plant a backdoor.

The malicious code grants operators persistent high-privilege access to the browser, enabling them to hijack affiliate links, inject tracking code, and commit click and ad fraud.

The hidden script is acting as a loader that fetches the main payload from a remote server. To make the process more difficult to detect, the payload is intentionally retrieved only once in ten attempts.

Wiz

Koi Security researchers discovered the GhostPoster campaign and identified 17 compromised Firefox extensions that either read the PNG logo to extract and execute the malware loader or download the main payload from the attacker's server.

It should be noted that the malicious extensions are from popular categories:

  1. free-vpn-forever
  2. screenshot-saved-easy
  3. weather-best-forecast
  4. crxmouse-gesture
  5. cache-fast-site-loader
  6. freemp3downloader
  7. google-translate-right-clicks
  8. google-traductor-esp
  9. world-wide-vpn
  10. dark-reader-for-ff
  11. translator-gbbd
  12. i-like-weather
  13. google-translate-pro-extension
  14. 谷歌-翻译
  15. libretv-watch-free-videos
  16. ad-stop
  17. right-click-google-translate

The researchers say that not all the extensions above use the same payload loading chain, but all of them exhibit the same behavior and communicate with the same infrastructure.

The FreeVPN Forever extension was the one Koi Security analyzed initially after its AI tool flagged it for parsing the raw bytes of its logo image file to locate a JavaScript snippet hidden using the steganography technique.

Malicious extension on the Firefox store
Malicious extension on the Firefox store
Source: Koi Security

The JavaScript loader activates 48 hours later to fetch a payload from a hardcoded domain. A second backup domain is available if the payload is not retrieved from the first one.

According to Koi Security , the loader is mostly dormant and gets the payload only 10% of the time, making it likely to evade detection from traffic monitoring tools.

The downloaded payload is heavily obfuscated via case swapping and base64 encoding. A cipher decodes it and then XOR-encrypts it using a key derived from the extension’s runtime ID.

Parsing the logo data for the malicious snippet
Parsing the logo data for the malicious snippet
Source: Koi Security

The final payload has the following capabilities:

  • Hijacks affiliate links on major e-commerce sites, redirecting commissions to the attackers.
  • Injects Google Analytics tracking into every page the user visits.
  • Strips security headers from all HTTP responses.
  • Bypasses CAPTCHA via three distinct mechanisms to circumvent bot protections.
  • Injects invisible iframes for ad fraud, click fraud, and tracking, which self-delete after 15 seconds.

Although the malware does not harvest passwords or redirect users to phishing pages, it still threatens user privacy.

Moreover, due to the stealthy loader employed by GhostPoster, the campaign could quickly become far more dangerous if the operator decides to deploy a more harmful payload.

Users of the listed extensions are recommended to remove them and should consider resetting passwords for critical accounts.

Many of the malicious extensions were still available on Firefox’s Add-Ons page at the time of writing. BleepingComputer has contacted Mozilla about it, but a comment wasn’t immediately available.

tines

Break down IAM silos like Bitpanda, KnowBe4, and PathAI

Broken IAM isn't just an IT problem - the impact ripples across your whole business.

This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

No AI* Here – A Response to Mozilla's Next Chapter

Hacker News
www.waterfox.com
2025-12-16 22:07:49
Comments...
Original Article

Mozilla’s new CEO recently announced their vision for the future : positioning Mozilla as “the world’s most trusted software company” with AI at its centre. As someone who has spent nearly 15 years building and maintaining Waterfox, I understand the existential pressure Mozilla faces. Their lunch is being eaten by AI browsers. Alphabet themselves reportedly see the writing on the wall, developing what appears to be a new browser separate from Chrome. The threat is real, and I have genuine sympathy for their position.

But I believe Mozilla is making a fundamental mistake.

The Asterisk Matters

Let’s be clear about what we’re talking about. “AI” has become a catch-all term that to me, obscures more than it reveals. Machine learning technologies like the Bergamot translation project offer real, tangible utility. Bergamot is transparent in what it does (translate text locally, period), auditable (you can inspect the model and its behavior), and has clear, limited scope, even if the internal neural network logic isn’t strictly deterministic.

Large language models are something else entirely˟. They are black boxes. You cannot audit them. You cannot truly understand what they do with your data. You cannot verify their behaviour. And Mozilla wants to put them at the heart of the browser and that doesn’t sit well.

But it’s important to note I do find LLMs have utility, measurably so. But here I am talking in the context of a web browser and the fundamental scepticism I have toward it in that context.

What Is a Browser For?

A browser is meant to be a user agent, more specifically, your agent on the web. It represents you, acts on your behalf, and executes your instructions. It’s called a user agent for a reason.

When you introduce a potential LLM layer between the user and the web, you create something different: “a user agent user agent” of sorts. The AI becomes the new user agent, mediating and interpreting between you and the browser. It reorganises your tabs. It rewrites your history. It makes decisions about what you see and how you see it, based on logic you cannot examine or understand.

Mozilla promises that “AI should always be a choice - something people can easily turn off.” That’s fine. But how do you keep track of what a black box actually does when it’s turned on? How do you audit its behaviour? How do you know it’s not quietly reshaping your browsing experience in ways you haven’t noticed?

Even if you can disable individual AI features, the cognitive load of monitoring an opaque system that’s supposedly working on your behalf would be overwhelming. Now, I truly believe and trust that Mozilla will do what they think is best for the user; but I’m not convinced it will be.

This isn’t paranoia, because after all, “It will evolve into a modern AI browser and support a portfolio of new and trusted software additions.” It’s a reasonable response to fundamentally untrustworthy technology being positioned as the future of web browsing.

Mozilla’s Dilemma?

I get it. Mozilla is facing an existential crisis. AI browsers are proliferating. The market is shifting. Revenue diversification from search is urgent. Firefox’s market share continues to decline. The pressure to “do something” must be immense, and I understand that.

But there’s a profound irony in their response. Mozilla speaks about trust, transparency, and user agency while simultaneously embracing technology that undermines all three principles. They promise AI will be optional, but that promise acknowledges they’re building AI so deeply into Firefox that an opt-out mechanism becomes necessary in the first place.

Mozilla’s strength has always come from the technical community - developers, power users, privacy advocates. These are the people who understand what browsers should be and what they’re for. Yet Mozilla seems convinced they need to chase the average user, the mainstream market that Chrome already dominates.

That chase has been failing for over a decade. Firefox’s market share has declined steadily as Mozilla added features their core community explicitly didn’t want. Now they’re doubling down on that strategy, going after “average Joe” users while potentially alienating the technical community that has been their foundation.

What Waterfox Offers Instead

Waterfox exists because some users want a browser that simply works well at being a browser. The UI is mature - arguably, it has been a solved for problem for years. The customisation features are available and apparent. The focus is on performance and web standards.

In many ways, browsers are operating systems of their own, and a browser’s job is to be a good steward of that environment. AI, in its current form and in my opinion does not match that responsibility.

And yes, yes - disabling features is all well and good, but at the end of the day, if these AI features are black boxes, how are we to keep track of what they actually do? The core browsing experience should be one that fully puts the user in control, not one where you’re constantly monitoring an inscrutable system that claims to be helping you.

Waterfox will not include LLMs. Full stop. At least and most definitely not in their current form or for the foreseeable future.

A Note on other Forks and Governance

The Firefox fork ecosystem includes several projects that tout their independence from Mozilla. Some strip out more features than Waterfox does, some make bolder design choices.

But here’s what often gets overlooked - many of these projects operate without any formal governance structure, privacy policies, or terms of service. There’s no legal entity, no accountability mechanism, no recourse if promises are broken. Open source gives developers the freedom to fork code and make claims, but it doesn’t automatically make those claims trustworthy.

When it comes to something as critical as a web browser - software that mediates your most sensitive online interactions - the existence of a responsible organisation with clear policies becomes crucial. Waterfox maintains formal policies and a legal entity, not because it’s bureaucratic overhead, but because it creates accountability that many browser projects simply don’t have.

You deserve to know who is responsible for the software you rely on daily and how decisions about your privacy are made. The existence of formal policies, even imperfect ones, represents a commitment that your interests matter and that there’s someone to hold accountable.

You may think, so what? And fair enough, I can’t change your mind on that, but Waterfox’s governance has allowed it to do something no other fork has (and likely will not do) - trust from other large, imporant third parties which in turn has given Waterfox users access to protected streaming services via Widevine. It’s a small thing, but to me it showcases the power of said governance.

On Inevitability

Some will argue that AI browsers are inevitable, that we’re fighting against the tide of history. Perhaps. AI browsers may eat the world. But the web, despite having core centralised properties, is fundamentally decentralised. There will always be alternatives. If AI browsers dominate and then falter, if users discover they want something simpler and more trustworthy, Waterfox will still be here, marching patiently along. We’ve been here before. When Firefox abandoned XUL extensions, Waterfox Classic preserved them. When Mozilla started adding telemetry and Pocket and sponsored content, Waterfox stripped it out. When the technical community asked for a browser that simply respected them, Waterfox delivered.

I’ll keep doing that. Not because it’s the most profitable path or because it’s trendy, but because it’s what users who value independence and transparency actually need.

The browser’s job is to serve you, not to think for you. That core Waterfox principle hasn’t changed, and it won’t.


* The asterisk acknowledges that “AI” has become a catch-all term. Machine learning tools like local translation engines (Bergamot) are valuable and transparent. Large language models, in their current black-box form, are neither.

˟ As is my understanding, but please feel free to correct me if that isn’t correct.

MIT professor shot at his Massachusetts home dies

Hacker News
www.bbc.com
2025-12-16 21:52:26
Comments...
Original Article

A Massachusetts university professor who was shot at his home has died, campus officials say.

Nuno F Gomes Loureiro, 47, a nuclear science and engineering professor from Portugal, was shot "multiple times" on Monday and died on Tuesday morning in hospital, according to Brookline police and Massachusetts Institute of Technology (MIT) officials.

Police said officers responded to a call for gunshots at an apartment at about 8:30pm local time. Loureiro was taken by ambulance to a Boston hospital, where he died on Tuesday morning.

No one is in custody and police are treating the incident as "an active and ongoing homicide investigation", the Norfolk County District Attorney's Office said.

CBS News, the BBC's US media partner, reported that a neighbour said he heard "three loud bangs" Monday evening and thought somebody in the apartment building was kicking in a door.

Long-time resident Anne Greenwald told CBS that the professor had a young family and went to school nearby.

Loureiro majored in Physics at Instituto Superior Técnico in Lisbon in 2000 and obtained a Phd in physics at Imperial College London in 2005, according to his faculty web page.

The theoretical physicist and fusion scientist was known for his award-winning research in magnetised plasma dynamics.

Magnetised plasma dynamics is the study of the state of matter in which the motion of charged particles is influenced by the presence of an external magnetic field, according to Nature.

Loureiro joined MIT's faculty in 2016 and was named director of MIT's Plasma Science and Fusion Center in 2024.

His research addressed "complex problems lurking at the center of fusion vacuum chambers and at the edges of the universe", according to the university's obituary.

He also studied how to harness clean "fusion power" to combat climate change, CBS said.

"Our deepest sympathies are with his family, students, colleagues, and all those who are grieving," an MIT spokesperson said in a statement provided to the BBC.

The university added that "focused outreach and conversations" are taking place within the MIT community to offer care and support for those who knew the professor.

The centre's preceding director, Dennis Whyte, described Loureiro as both a brilliant scientist and a brilliant person.

"He shone a bright light as a mentor, friend, teacher, colleague and leader, and was universally admired for his articulate, compassionate manner," Mr Whyte told MIT News.

Deepto Chakrabarty, the head of MIT's department of physics, echoed those sentiments and said that Loureiro was a champion of plasma physics and that his recent research was "a particularly exciting new scientific direction".

Correction 16 December: An earlier version of this story incorrectly defined the kind of plasma that Professor Loureiro researched.

Reverse-Engineering the RK3588 NPU: Hacking Limits to Run Vision Transformers

Hacker News
amohan.dev
2025-12-16 21:18:46
Comments...
Original Article

Author's Note: I am currently an MS CS student at CU Boulder specializing in Edge AI & Embedded Systems. I am actively looking for Summer 2026 Internships where I can optimize difficult workloads on constrained silicon.

📄 Resume | ✉️ Email | 💻 GitHub

The “Unsupported” Hardware Problem

If you look at the spec sheet for the Rockchip RK3588 (the chip inside the Orange Pi 5), it looks like a beast. It promises 6 TOPS of NPU performance. For $100, that’s a steal.

But if you try to run modern AI on it—specifically the Vision Encoder from SmolVLM —that promise falls apart.

The standard Computer Vision SDK ( rknn-toolkit2 ) is optimized for older, predictable CNNs (like ResNet). When I fed it the SigLIP Vision Transformer used by SmolVLM, the driver choked. Even though the model is “smol,” the massive Attention matrices it generates triggered cryptic hex errors and refused to compile.

This left me with one option: running the model on the CPU. The result? A single image inference took ~30 seconds . The 6 TOPS accelerator sat idle while the CPU struggled.

I didn’t accept that. I decided to reverse-engineer the NPU to find out exactly why it was failing, and how to force it to run at full speed.

Context: Why do it the hard way? (First Principles)

A quick note for those following the ecosystem: You might see projects like QEngineering running the newer SmolVLM-v2 on Rockchip’s rknn-llm SDK.

That approach uses a specialized “black box” toolchain designed specifically for Transformers. Rockchip engineers have likely already implemented complex memory management inside that SDK to handle these models.

My project targets the original SmolVLM-v1 , but more importantly, I built it on the legacy rknn-toolkit2 stack . Why hack the legacy stack? I wanted to take a “First Principles” approach. I didn’t want to use a black-box solver. I wanted to understand why the hardware was crashing on Attention layers and if I could find universal architectural patterns—like manual tiling and graph sharding—that could force any Transformer to run on any constrained edge accelerator.

The Detective Work: What is Error 0xe010 ?

Rockchip doesn’t publish a public Instruction Set Architecture (ISA). When I tried to compile the Attention layers, the driver kept spitting out an undocumented error: REGTASK Overflow (0xe010) .

I hypothesized this was a memory overflow. Even though the model parameters are small (~96M), the intermediate activation matrices for a 1024-token sequence are huge (~25MB).

I wrote a script to generate synthetic ONNX graphs to probe the hardware limits:

  • 8KB Tensor: Pass.
  • 16KB Tensor: Pass.
  • 32KB Tensor: Pass.
  • 32.1KB Tensor: CRASH.

Discovery: The NPU has a hardware-enforced 32KB L1 SRAM Scratchpad for vector operations.

The standard compiler was trying to shove a 25MB Attention matrix into a 32KB slot.

The Fix: Nano-Tiling & The “Poison Pill”

To solve the 32KB limit, I wrote a “Nano-Tiling” algorithm in PyTorch. I manually sliced the massive 1024-token sequence into tiny 32x32 tiles that fit perfectly into the 32KB scratchpad.

But here is where it got messy. The rknn compiler is “smart.” It looked at my tiled graph, decided it was inefficient, and fused the operators back together into a single giant block… which immediately crashed the hardware again.

I had to trick the compiler. I needed a way to tell it: “Do not merge these nodes.”

I introduced a topological barrier I call the “Poison Pill.” I injected a dummy operation that looks mathematically significant to the dependency graph (preventing fusion) but is mathematically irrelevant to the model output.

# The "Poison Pill"
# 1. Take a slice (forcing a strided access)
slice_x = x[..., :1]

# 2. Apply a non-linear op (breaks compiler fusion heuristics)
# 3. Scale it down to near-zero so it doesn't affect the math
poison = torch.sigmoid(slice_x) * 1e-6 

# 4. Inject dependency
# The compiler sees 'out' depends on 'poison' and creates a barrier.
out = out + poison

By injecting this into the graph, I successfully forced the compiler to respect my tiling logic.

The “SigLIP Cliff”: Solving Accuracy Collapse

Getting it to run was step one. Getting it to be right was step two. When I first got the NPU running, the output was garbage. The cosine similarity compared to the original model was 0.02 (pure noise).

The culprit was the architecture of SigLIP . Unlike standard models, SigLIP has massive activation “spikes” (values around 300.0 ) sitting next to tiny visual signals (values around 0.05 ).

NPU quantization (INT8) works by mapping the range to -128/+127.

  • If you zoom out to capture the 300.0 , the 0.05 rounds down to 0. Signal lost.
  • If you zoom in to capture the 0.05 , the 300.0 overflows to infinity. Math crash.

I implemented a “Sandwich” Domain Shift :

  1. CPU Pre-Scale: Multiply the input by 0.1 . Now the max value is 30.0 (Safe for FP16).
  2. NPU Execution: Run the heavy compute in this scaled-down “safe zone.”
  3. CPU Post-Scale: Multiply the output by 10.0 .

This simple trick restored the signal fidelity from 0.02 to 0.999 (effectively bit-exact).

The Architecture: Custom Runtime Scheduler

Finally, to bypass driver timeouts caused by the sheer number of tiles (thousands of tiny operations), I physically cut the model graph into 26 separate binary files (shards).

I wrote a custom User-Space Runtime in Python that acts as an orchestrator. It manually loads these shards onto the RK3588’s 3 separate NPU cores and fires them in a synchronized round-robin schedule (Core 0 -> Core 1 -> Core 2).

The Results

By ignoring the vendor’s “Unsupported” warnings and re-architecting the software to match the silicon’s physical reality, the results were drastic.

Metric CPU Baseline (PyTorch) SHARD (My Method)
Latency ~30.0 seconds < 1.8 seconds
Speedup 1x 15x
Accuracy Reference 0.999 (FP32 Match)

Conclusion

This project challenged the binary notion of “Supported Hardware.” The RK3588 didn’t support the SigLIP encoder out of the box on the standard SDK, but the silicon was always capable of it. It just needed an engineer to dig into the register overflow codes and manage the memory manually.

If you want to see the full code, including the tiling logic and the runtime orchestrator, check out the repo below.

View Source on GitHub

Chat-tails: Throwback terminal chat, built on Tailscale

Hacker News
tailscale.com
2025-12-16 21:16:35
Comments...
Original Article

To find a safe space for his kid to chat with friends while playing Minecraft, Brian Scott had to go back to the future.

The chat went back, that is, to an IRC-like interface, run through a terminal. The connection and setup remain futuristic, because Scott used Tailscale , and tsnet , to build chat-tails .

Chat-tails is the opposite of everything modern chat apps are offering. Nobody can get in without someone doing some work to invite them. All the chats are ephemeral, stored nowhere easy to reach, unsearchable. There are no voice chats, plug-ins, avatars, or images at all, really, unless you count ASCII art . And that’s just the way Brian wanted it.

“It’s about, hey, you have this private space, across your friends’ tailnets, where you can chat, about the game you’re playing or whatever you’re doing,” Scott told me. “It’s supposed to be more like the days where you were all on the same LAN, you would bring your computers together and have a gaming session. Now you can kind of have that same type of feeling, no matter where you are in the world—just a nice private area where you can chat.”

How it works

There are two ways of running chat-tails: “Regular mode” and “Tailscale mode.” In Regular Mode, you run ./chat-server , feed it a port number, room name, and maximum number of users, and then it creates the chat, on your local network. You can log into your router and enable a port forward, if you want, every time you create the chat and want to let others in—but opening up a telnet-style chat port on your home router, the one you’re having your kids chat on, seems like a pretty bad idea. Your mileage may vary.

In “Tailscale Mode,” you do all the same things, except you provide two more things. One is a --hostname , which makes the chat accessible (to Tailscale users with whom you’ve shared this chat) at your Tailscale domain, like hostname.something.ts.net . The other thing you give it is an auth key , connecting it to Tailscale. With that, any device on the tailnet, or shared into it, can access the chat through an nc or telnet command, like telnet hostname.something.ts.net 2323 .

And then you are chatting, in a terminal. Type some text, hit enter, and everyone sees it. There are four other commands, as of this writing: /who lists the users, /help shows you these four commands, /me gives your text the italicized “action” flavor (“reaches for an ice-cold Diet Coke”), and /quit , it quits. That’s the app, and while it might pick up some features over time (it added history options just recently), it’s doing just what it should right now.

A chat window, showing a list of users with colored names (Kevin, Other_Kevin, Devon), a conversation ("You both are Kevins?" "I'm an Other_Kevin" "* Kevin considers this statement"), and then the list of commands.

Building an old-school chat space

Scott is not a full-time code-writing developer, but has about 10 years’ experience working with Go. He had been eyeing the tsnet library for some time, thinking of projects that might fit a melding of Go and Tailscale. When his chat inspiration (chatspiration?) struck, he spent “about two days” learning and tinkering with the library for the first big effort.

“The tsnet (library) was actually the easiest thing,” Brian said. With the networking and verification pieces sorted, he just had to focus on the surprisingly hard task of getting text that one person types in a terminal to show up as text that another terminal user reads. “If you’re thinking of building something like Discord, you would incorporate some kinds of websocket communication, streamline everything across the wire. But for a terminal-based chat app, it’s really just TCP and UDP, just straight-up connections you’re actually dealing with.”

Making the chat look nicer than just a terminal line was helped along by bubbletea, a free and open-source terminal UI library. “While I was making this thing very minimal, I wanted to also make it very pleasing,” Brian said.

Anyone with experience building in Go could extend it or modify it, Brian said. He has looked at Go libraries for things like rendering images in terminal chat, and thought about how Taildrop could be used in a chat where everybody’s using Tailscale. Chat-tails is low-profile enough to easily run on a Raspberry Pi or similarly single-board computer (SBC); it might be leveraged as a portable, ephemeral chat to bring to events. Or it could just become a way for groups with a certain retro bent to replace their personal Slack or Discord setups.

But for now, it’s a fun way to offer his child and friends a safe learning space.

“You launch it on top of Tailscale, scale it as big as you want, and now your community is not only learning about VPN technology, but also the basics of SSH, terminal, things like that,” Brian said. “It feels good, very retro-futuristic, and fun.”

Brian’s chat-tails is included in our community projects hub . Built something neat with Tailscale? Submit it by email community@tailscale.com .

If you’re enjoying chat-tails, or other community projects, we’ve got a whole channel for that in our Discord, #community-projects . We’re also listening and sharing great projects on Reddit , Bluesky , Mastodon , and LinkedIn .

Prediction: AI will make formal verification go mainstream

Hacker News
martin.kleppmann.com
2025-12-16 21:14:49
Comments...
Original Article

Published by Martin Kleppmann on 08 Dec 2025.

Much has been said about the effects that AI will have on software development, but there is an angle I haven’t seen talked about: I believe that AI will bring formal verification, which for decades has been a bit of a fringe pursuit, into the software engineering mainstream.

Proof assistants and proof-oriented programming languages such as Rocq , Isabelle , Lean , F* , and Agda have been around for a long time. They make it possible to write a formal specification that some piece of code is supposed to satisfy, and then mathematically prove that the code always satisfies that spec (even on weird edge cases that you didn’t think of testing). These tools have been used to develop some large formally verified software systems, such as an operating system kernel , a C compiler , and a cryptographic protocol stack .

At present, formal verification is mostly used by research projects, and it is uncommon for industrial software engineers to use formal methods (even those working on classic high-assurance software such as medical devices and aircraft). The reason is that writing those proofs is both very difficult (requiring PhD-level training) and very laborious.

For example, as of 2009, the formally verified seL4 microkernel consisted of 8,700 lines of C code, but proving it correct required 20 person-years and 200,000 lines of Isabelle code – or 23 lines of proof and half a person-day for every single line of implementation. Moreover, there are maybe a few hundred people in the world (wild guess) who know how to write such proofs, since it requires a lot of arcane knowledge about the proof system.

To put it in simple economic terms: for most systems, the expected cost of bugs is lower than the expected cost of using the proof techniques that would eliminate those bugs. Part of the reason is perhaps that bugs are a negative externality: it’s not the software developer who bears the cost of the bugs, but the users. But even if the software developer were to bear the cost, formal verification is simply very hard and expensive.

At least, that was the case until recently. Now, LLM-based coding assistants are getting pretty good not only at writing implementation code, but also at writing proof scripts in various languages . At present, a human with specialist expertise still has to guide the process, but it’s not hard to extrapolate and imagine that process becoming fully automated in the next few years. And when that happens, it will totally change the economics of formal verification.

If formal verification becomes vastly cheaper, then we can afford to verify much more software. But on top of that, AI also creates a need to formally verify more software: rather than having humans review AI-generated code, I’d much rather have the AI prove to me that the code it has generated is correct. If it can do that, I’ll take AI-generated code over handcrafted code (with all its artisanal bugs) any day!

In fact, I would argue that writing proof scripts is one of the best applications for LLMs. It doesn’t matter if they hallucinate nonsense, because the proof checker will reject any invalid proof and force the AI agent to retry. The proof checker is a small amount of code that is itself verified, making it virtually impossible to sneak an invalid proof past the checker.

That doesn’t mean software will suddenly be bug-free. As the verification process itself becomes automated, the challenge will move to correctly defining the specification: that is, how do you know that the properties that were proved are actually the properties that you cared about? Reading and writing such formal specifications still requires expertise and careful thought. But writing the spec is vastly easier and quicker than writing the proof by hand, so this is progress.

I could also imagine AI agents helping with the process of writing the specifications, translating between formal language and natural language. Here there is the potential for subtleties to be lost in translation, but this seems like a manageable risk.

I find it exciting to think that we could just specify in a high-level, declarative way the properties that we want some piece of code to have, and then to vibe code the implementation along with a proof that it satisfies the specification. That would totally change the nature of software development: we wouldn’t even need to bother looking at the AI-generated code any more, just like we don’t bother looking at the machine code generated by a compiler.

In summary: 1. formal verification is about to become vastly cheaper; 2. AI-generated code needs formal verification so that we can skip human review and still be sure that it works; 3. the precision of formal verification counteracts the imprecise and probabilistic nature of LLMs. These three things taken together mean formal verification is likely to go mainstream in the foreseeable future. I suspect that soon the limiting factor will not be the technology, but the culture change required for people to realise that formal methods have become viable in practice.

If you found this post useful, please support me on Patreon so that I can write more like it!

To get notified when I write something new, follow me on Bluesky or Mastodon , or enter your email address:

I won't give your address to anyone else, won't send you any spam, and you can unsubscribe at any time.

ty: An extremely fast Python type checker and language server

Lobsters
astral.sh
2025-12-16 21:11:40
Comments...
Original Article

TL;DR: ty is an extremely fast Python type checker and language server , written in Rust, and designed as an alternative to tools like mypy, Pyright, and Pylance.

Today, we're announcing the Beta release of ty . We now use ty exclusively in our own projects and are ready to recommend it to motivated users for production use.


At Astral, we build high-performance developer tools for the Python ecosystem. We're best known for uv , our Python package manager, and Ruff , our linter and formatter.

Today, we're announcing the Beta release of the next tool in the Astral toolchain: ty, an extremely fast Python type checker and language server , written in Rust.

0s 20s 40s ty Pyrefly Pyright mypy 5.32s 19.62s 45.66s 2.19s

Type checking the home-assistant project on the command-line, without caching ( M4 ).

ty was designed from the ground up to power a language server. The entire ty architecture is built around "incrementality", enabling us to selectively re-run only the necessary computations when a user (e.g.) edits a file or modifies an individual function. This makes live updates extremely fast in the context of an editor or long-lived process.

0s 1s 2s ty Pyright Pyrefly 370.5ms 2.60s 4.5ms

Re-computing diagnostics in the language server after editing a file in the PyTorch project ( M4 ).

You can install ty today with uv tool install ty@latest , or via our VS Code extension .

Like Ruff and uv, ty's implementation was grounded in some of our core product principles:

  1. An obsessive focus on performance. Without caching, ty is consistently between 10x and 60x faster than mypy and Pyright. When run in an editor, the gap is even more dramatic. As an example, after editing a load-bearing file in the PyTorch repository, ty recomputes diagnostics in 4.7ms: 80x faster than Pyright (386ms) and 500x faster than Pyrefly (2.38 seconds). ty is very fast!

  2. Correct, pragmatic, and ergonomic. With features like first-class intersection types , advanced type narrowing , and sophisticated reachability analysis , ty pushes forward the state of the art in Python type checking, providing more accurate feedback and avoiding assumptions about user intent that often lead to false positives. Our goal with ty is not only to build a faster type checker; we want to build a better type checker, and one that balances correctness with a deep focus on the end-user experience.

  3. Built in the open. ty was built by our core team alongside dozens of active contributors under the MIT license, and the same goes for our editor extensions . You can run ty anywhere that you write Python (including in the browser ).

Even compared to other Rust-based language servers like Pyrefly, ty can run orders of magnitude faster when performing incremental updates on large projects.

Editing a central file in the PyTorch repository with ty (left) and Pyrefly (right). ty's incremental architecture is designed to make live updates extremely fast.

ty also includes a best-in-class diagnostic system , inspired by the Rust compiler's own world-class error messages. A single ty diagnostic can pull in context from multiple files at once to explain not only what's wrong, but why (and, often, how to fix it).

ty diagnostic showing an invalid assignment error to a TypedDict key with reference to the item declaration

ty diagnostic showing an invalid assignment error to a TypedDict key with reference to the item declaration

When assigning an invalid value to a dictionary key, ty surfaces both the type mismatch at the assignment site and the corresponding item declaration.

Diagnostic output is the primary user interface for a type checker; we prioritized our diagnostic system from the start (with both humans and agents in mind) and view it as a first-class feature in ty.

ty diagnostic showing an unresolved import error for tomllib module with reference to Python version configuration

ty diagnostic showing an unresolved import error for tomllib module with reference to Python version configuration

When importing an unresolved module, ty surfaces both the unresolved import at the import site and the corresponding Python version configuration.

If you use VS Code, Cursor, or a similar editor, we recommend installing the ty VS Code extension . The ty language server supports all the capabilities that you'd expect for a modern language server (Go to Definition, Symbol Rename, Auto-Complete, Auto-Import, Semantic Syntax Highlighting, Inlay Hints, etc.), and runs in any editor that implements the Language Server Protocol .

Following the Beta release, our immediate priority is supporting early adopters. From there, we're working towards a Stable release next year, with the gap between the Beta and Stable milestones largely focusing on: (1) stability and bug fixes, (2) completing the long tail of features in the Python typing specification , and (3) first-class support for popular third-party libraries like Pydantic and Django .

On a longer time horizon, though, ty will power semantic capabilities across the Astral toolchain: dead code elimination, unused dependency detection, SemVer-compatible upgrade enforcement, CVE reachability analysis, type-aware linting, and more (including some that are too ambitious to say out loud just yet).

We want to make Python the most productive programming ecosystem on Earth. Just as with Ruff and uv , our commitment from here is that ty will get significantly better every week by working closely with our users. Thank you for building with us.

Acknowledgements #

ty is the most sophisticated product we've built, and its design and implementation have surfaced some of the hardest technical problems we've seen at Astral. Working on ty requires a deep understanding of type theory, Python runtime semantics, and how the Python ecosystem actually uses Python.

I'd like to thank all those that contributed directly to the development of ty, including: Douglas Creager , Alex Waygood , David Peter , Micha Reiser , Andrew Gallant , Aria Desires , Carl Meyer , Zanie Blue , Ibraheem Ahmed , Dhruv Manilawala , Jack O'Connor , Zsolt Dollenstein , Shunsuke Shibayama , Matthew Mckee , Brent Westbrook , UnboundVariable , Shaygan Hooshyari , Justin Chapman , InSync , Bhuminjay Soni , Abhijeet Prasad Bodas , Rasmus Nygren , lipefree , Eric Mark Martin , Luca Chiodini , Brandt Bucher , Dylan Wilson , Eric Jolibois , Felix Scherz , Leandro Braga , Renkai Ge , Sumana Harihareswara , Takayuki Maeda , Max Mynter , med1844 , William Woodruff , Chandra Kiran G , DetachHead , Emil Sadek , Jo , Joren Hammudoglu , Mahmoud Saada , Manuel Mendez , Mark Z. Ding , Simon Lamon , Suneet Tipirneni , Francesco Giacometti , Adam Aaronson , Alperen Keleş , charliecloudberry , Dan Parizher , Daniel Hollas , David Sherret , Dmitry , Eric Botti , Erudit Morina , François-Guillaume Fernandez , Fabrizio Damicelli , Guillaume-Fgt , Hugo van Kemenade , Josiah Kane , Loïc Riegel , Ramil Aleskerov , Samuel Rigaud , Soof Golan , Usul-Dev , decorator-factory , omahs , and wangxiaolei .

We'd also like to thank the Salsa team (especially Niko Matsakis , David Barsky , and Lukas Wirth ) for their support and collaboration; the Elixir team (especially José Valim , Giuseppe Castagna , and Guillaume Duboc ), whose work strongly influenced our approach to gradual types and intersections; and a few members of the broader Python typing community: Eric Traut , Jelle Zijlstra , Jia Chen , Sam Goldman , Shantanu Jain , and Steven Troxler .

Finally, on a personal level, I'd like to highlight the core team ( Alex , Andrew , Aria , Carl , David , Dhruv , Doug , Ibraheem , Jack , and Micha ), who created ty from nothing and pushed it to be great from Day 1.

Show HN: Deterministic PCIe Diagnostics for GPUs on Linux

Hacker News
github.com
2025-12-16 21:03:25
Comments...
Original Article

GPU PCIe Diagnostic & Bandwidth Analysis

A deterministic command-line tool for validating GPU PCIe link health, bandwidth, and real-world PCIe utilization using only observable hardware data.

This tool answers one question reliably:

Is my GPU’s PCIe link behaving as it should, and can I prove it?

No registry hacks. No BIOS assumptions. No “magic” optimizations.

Only measurable link state, copy throughput, and hardware counters.

What This Tool Does

This tool performs hardware-observable PCIe diagnostics and reports factual results with deterministic verdicts.

It measures and reports directly from GPU hardware:

  • PCIe current and maximum link generation and width (via NVML)
  • Peak Host→Device and Device→Host copy bandwidth using CUDA memcpy timing
  • Sustained PCIe utilization under load using NVML TX/RX counters
  • Efficiency relative to theoretical PCIe payload bandwidth
  • Clear VERDICT from observable conditions only

The tool does not attempt to tune, fix, or modify system configuration.

Verdict Semantics

  • OK — The negotiated PCIe link and measured throughput are consistent with expected behavior.
  • DEGRADED — The GPU is operating below its maximum supported PCIe generation or width.
  • UNDERPERFORMING — The full link is negotiated, but sustained bandwidth is significantly lower than expected.

Verdicts are rule-based and derived only from measured data.

Why This Tool Exists

Modern systems frequently exhibit PCIe issues that are difficult to diagnose:

  • GPUs negotiating x8 / x4 / x1 instead of x16
  • PCIe generation downgrades after BIOS or firmware updates
  • Slot bifurcation, riser cable, or motherboard lane-sharing issues
  • Reduced PCIe bandwidth occurring while system status is reported as normal
  • Confusion between PCIe transport limits and workload bottlenecks

This tool exists to:

  1. Reproducible PCIe diagnostic baseline
  2. Hardware-level proof of PCIe behavior
  3. Isolate link negotiation from kernel/workload effects

Example Output

GPU PCIe Diagnostic & Bandwidth Analysis v2.7.4
GPU:   NVIDIA GeForce GTX 1080
BDF:   00000000:01:00.0
UUID:  GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (redacted)

PCIe Link
  Current: Gen3 x16
  Max Cap: Gen3 x16
  Theoretical (payload): 15.76 GB/s
  Transfer Size: 1024 MiB

Peak Copy Bandwidth
  Host → Device: 12.5 GB/s
  Device → Host: 12.7 GB/s

Telemetry (NVML)
  Window:   5.0 s (50 samples @ 100 ms)
  TX avg:   7.6 GB/s
  RX avg:   7.1 GB/s
  Combined: 14.7 GB/s

Verdict
  State:      OK
  Reason:     Throughput and link state are consistent with a healthy PCIe path
  Efficiency: 93.5%

System Signals (informational)
  MaxReadReq: 512 bytes
  Persistence Mode: Disabled
  ASPM Policy (sysfs string): [default] performance powersave powersupersave
  IOMMU: Platform default (no explicit flags)

Requirements

  • NVIDIA GPU with a supported driver
  • CUDA Toolkit (for nvcc )
  • NVML development library ( -lnvidia-ml )

Platform Compatibility Note

  • Linux operating system
  • Tested on Ubuntu 24.04.3 LTS

Permissions & Logging Notes

On some Linux systems, PCIe and NVML diagnostics require elevated privileges due to kernel and driver access controls. If log files were previously created using sudo , the results directory may become root-owned. In that case, subsequent runs may prompt for a password when appending logs.

To restore normal user access to the results directory:

sudo chown -R $USER:$USER results/

Build

make

or manually:

nvcc -O3 pcie_diagnostic_pro.cu -lnvidia-ml -Xcompiler -pthread -o pcie_diag

Usage

./pcie_diag 1024

Logging

./pcie_diag 1024 --log --csv ./pcie_diag 1024 --log --json ./pcie_diag 1024 --log --csv --json

Logs are written to:

  • results/csv/pcie_log.csv
  • results/json/pcie_sessions.json

Extended Telemetry Window

./pcie_diag 1024 --duration-ms 8000

  • improves measurement stability

Optional Integrity Counters

./pcie_diag 1024 --integrity

  • Enables read-only inspection of PCIe Advanced Error Reporting (AER) counters via Linux sysfs, if exposed by the platform.
  • If counters are unavailable on the platform, integrity checks are automatically skipped with clear reporting.

Multi-GPU Logging Behavior

When running in multi-GPU mode ( --all-gpus ), each detected GPU is evaluated independently.

  • One result row (CSV) or object (JSON) is emitted per GPU per run.
  • Each entry includes device UUID and PCIe BDF for unambiguous attribution.
  • Multi-GPU configurations have not been exhaustively validated on all platforms.
  • Users are encouraged to verify results on their specific hardware.

Example:

./pcie_diag 1024 --all-gpus --log --csv
./pcie_diag 1024 --all-gpus --log --json 
./pcie_diag 1024 --gpu-index 1     # Target single GPU by index

Logging & Reproducibility

  • CSV and JSON logs include stable device identifiers
  • Device UUIDs are reported at runtime via NVML for consistent identification across runs
  • UUIDs shown in documentation are intentionally redacted
  • Logs are append-friendly for time-series analysis and automated monitoring

Scope & Limitations

  • This tool evaluates PCIe transport behavior only
  • It does not measure kernel performance or application-level efficiency
  • It does not modify BIOS, firmware, registry, or PCIe configuration
  • It reports observable facts only and never infers beyond available data

Validation

  • Memcpy timing and PCIe behavior were cross-validated during development using Nsight Systems.
  • Nsight is not required to use this tool and is referenced only as an external correctness check.

Author

Author: Joe McLaren (Human–AI collaborative engineering) https://github.com/parallelArchitect

License

MIT License

Copyright (c) 2025 Joe McLaren

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

References

Letta Code

Hacker News
www.letta.com
2025-12-16 20:51:27
Comments...
Original Article

Letta Code is a memory-first coding agent, designed for working with agents that learn over time. When working with coding agents today, interactions happen in independent sessions. Letta Code is built around long-lived agents that persist across sessions and improve with use. Rather than working in independent sessions, each session is tied to a persisted agent that learns. Letta Code is also the #1 model-agnostic OSS harness on TerminalBench, and achieves comparable performance to harnesses built by LLM providers ( Claude Code , Gemini CLI , Codex CLI ) on their own models.

Continual Learning & Memory for Coding Agents

Agents today accumulate valuable experience: they receive the user’s preferences and feedback, review significant parts of code, and observe the outcomes of taking actions like running scripts or commands. Yet today this experience is largely wasted. Letta agents learn from experience through agentic context engineering , long-term memory , and skill learning . The more you work with an agent, the more context and memory it accumulates, and the better it becomes.

Memory Initialization

When you get started with Letta Code, you can run an `/init` command to encourage your agent to learn about your existing project. This will trigger your agent to run deep research on your local codebase, forming memories and rewriting its system prompt (through memory blocks ) as it learns.

Your agent will continue to learn automatically, but you can also explicitly trigger your agent to reflect and learn with the `/remember` command.

Skill Learning

Many tasks that we work on with coding agents are repeated or follow similar patterns - for example API patterns or running DB migrations. Once you’ve worked with an agent to coach it through a complex task, you can trigger it to learn a skill from its experience, so the agent itself or other agents can reference the skill for similar tasks in the future. Skill learning can dramatically improve performance on future similar tasks, as we showed with recent results on TerminalBench.

On our team, some skills that agents have contributed (with the help of human engineers) are:

  • Generating DB migrations on schema changes
  • Creating PostHog dashboards with the PostHog CLI
  • Best practices for API changes

Since skills are simply .md files, they can be managed in git repositories for versioning - or even used by other coding agents that support skills.

Persisted State

Agents can also lookup past conversations (or even conversations of other agents) through the Letta API . The builtin `/search` command allows you to easily search through messages, so you can find the agent you worked on something with. The Letta API supports vector, full-text, and hybrid search over messages and available tools .

Letta Code is the #1 model-agnostic OSS coding harness

Letta Code adds statefulness and learning to coding agents, but is the #1 model-agnostic, OSS harness on Terminal-Bench . Letta Code’s performance is comparable to provider-specific harnesses (Gemini CLI, Claude Code, Codex) across model providers, and significantly outperforms the previous leading model-agnostic harness, Terminus 2.

This means that even without memory, you can expect Letta Code agents to work just as well with a frontier model as they would with a specific harness built by the model provider.

Getting Started with Letta Code

To try out Letta Code, you can install it with npm install -g @letta-ai/letta-code or install from source (see the full documentation ).

Letta Code can be used with the Letta Developer Platform , or with a self-hosted Letta server.

Longtime Paid FBI Informant Was Instrumental in Terror Case Against “Turtle Island Liberation Front”

Intercept
theintercept.com
2025-12-16 20:37:22
Kash Patel and others touted the FBI’s investigative work, but the few available details point to a more complicated picture. The post Longtime Paid FBI Informant Was Instrumental in Terror Case Against “Turtle Island Liberation Front” appeared first on The Intercept....
Original Article

An FBI investigation into an alleged terror plot in Southern California bears the familiar hallmarks of the bureau’s long-running use of informants and undercover agents to advance plots that might not otherwise have materialized, court documents show.

News of the plot surfaced Monday morning in a Fox News report that ran ahead of court filings or official statements. Within minutes, FBI officials amplified the story on social media.

“PROTECT THE HOMELAND and CRUSH VIOLENT CRIME,” wrote FBI Deputy Director Dan Bongino, a former podcaster. “These words are not slogans, they’re the investigative pillars of this FBI.”

The informant and the undercover agent were involved in nearly every stage of the case.

What followed, however, painted a more complicated picture.

The limited details available suggest an investigation that leaned heavily on a paid informant and at least one undercover FBI agent, according to an affidavit filed in federal court. The informant and the undercover agent were involved in nearly every stage of the case, including discussions of operational security and transporting members of the group to the site in the Mojave Desert where federal agents ultimately made the arrests.

The informant, who has worked other cases on the FBI’s payroll since 2021, had been in contact with the group known as the Turtle Island Liberation Front since at least late November, just two months after President Donald Trump designated “antifa” a domestic terrorism organization.

On the morning of December 15, FBI Director Kash Patel announced the arrests, calling the plot “a credible, imminent terrorist threat.”

Yet the case had the familiar markings of FBI terrorism stings that stretch back more than two decades — hundreds of cases that have disproportionately targeted left-wing activists and Muslims , and, less often, right-wing actors .

“Bring Cases, Get Paid”

Since the September 11 attacks, the FBI has relied on informants to identify and build terrorism cases. The structure has created perverse incentives for potential informants. Their cooperation can get them out of criminal cases of their own and lead to handsome monetary compensation. The FBI’s call is simple: Bring cases, get paid.

Rick Smith, a security consultant and former FBI agent, said confidential sources are essential to investigative police work, but cautioned that they come with inherent baggage.

“They’re sources, they’re not ordinary citizens,” Smith said. “They have either been compromised in some way, or they’re going to be paid. Either way, they’ve got some sort of skin in the game. They’re getting something out of it.”

In the years after 2001 attacks, the FBI created a market for cases involving left-wing activists and Muslims. After the January 6 Capitol riot, the bureau made clear to informants that right-wing extremism was a priority. Now, under the second Trump administration, the federal government’s focus is again turning to perceived left-wing extremism .

In September, days after the terror designation of antifa, Trump outlined his administration’s war on the left in a memo titled National Security Presidential Memorandum 7, or NSPM-7 , which called for the National Joint Terrorism Task Force to coordinate with local offices to investigate alleged federal crimes by political radicals. The head of the federal prosecutor’s office in Los Angeles said on Monday that the Turtle Island Liberation Front arrests stemmed from Trump’s executive order .

Key questions in the Turtle Island Liberation Front case, however, remain unanswered. It is still unclear how the FBI first identified the group or how long the informant had been embedded before the bomb plot emerged — a period defense attorneys say is central to any serious examination of entrapment , whereby defendants are coerced into crimes they would not otherwise commit, a frequent criticism of stings involving paid informants and undercover agents .

“The question that immediately popped into my mind was that: There’s a reference to a confidential human source, but there’s no indication of how that source came to be,” said Brad Crowder, an activist and union organizer who was convicted in a case of alleged violent protest plans that involved a confidential informant. “It’s not totally out of the realm of possibilities that this idea was planted or floated by whoever this confidential human source might be.”

Turtle Island Case

Despite comments from Attorney General Pam Bondi, Patel, and others characterizing the Turtle Island Liberation Front as a coherent group and a Signal chat called “Black Lotus” as an ultra-radical subset, there’s little evidence that any group by that name exists beyond a small digital footprint and a handful of attempts at organizing community events, including a self-defense workshop and a punk rock benefit show planned for February.

The Instagram page for the Turtle Island Liberation Front cited in the complaint had just over 1,000 followers as of Tuesday morning — after it was widely publicized — and its first post came in late July. The YouTube channel bearing the group’s name, which had just 18 subscribers as of Tuesday morning, was registered on July 17 and contains a single video posted on September 16.

Online, the group styled itself as radical and righteous. Its activists spoke in the language of solidarity with Palestinians and Indigenous people, railing against U.S. Immigration and Customs Enforcement and American power. On Instagram, they posted slogans and absolutes:

“Become a revolutionary.”

“America has always been the brutal evil monster that some of you don’t want to face.”

“Resistance is the deepest form of love.”

The informant did not, however, meet with the group on November 26 for its slogans.

According to the affidavit, the informant met up with Audrey Illeene Carroll, who went by the nickname Asiginaak. At the meeting, Carroll handed over eight pages covered with handwriting in blue ink. The document was titled “Operation Midnight Sun,” and laid out a plan to detonate backpack bombs at five separate locations on New Year’s Eve, when fireworks would mask the sound of explosions. The plan was unfinished. Beneath the list of targets were blank lines, marked: “add more if enough comrades.” (Carroll’s attorney did not immediately respond to a request for comment.)

Over the following weeks, the plot advanced, according to court filings. A Signal group was created for, in the participants’ words, “everything radical,” including the bomb plan itself. On December 7, the supposed bomb plot expanded to include an undercover FBI agent. At that meeting, Carroll distributed pages describing how to build the bombs. She said she already had 13 PVC pipes cut to size and had ordered two five-pound bags of potassium nitrate from Amazon, believing naively that a burner account she set up was keeping her anonymous. Delivery was scheduled for December 11.

The FBI allowed the plan to progress, with both an informant and an undercover agent actively participating.

The FBI had visibility into nearly every part of the supply chain: chemicals ordered online and pistol primers purchased at a retail store. Agents could have intervened at any stage. They didn’t. Instead, the bureau allowed the plan to continue, with both an informant and an undercover agent actively participating in the conspiracy.

On December 12, the group drove into the desert with an aim of testing the bombs. They took two vehicles: the informant in one, the undercover agent in the other. Riding with the undercover agent was Zachary Aaron Page, who went by the nickname AK. He suggested using cigarettes as a delayed fuse. In the other car, Carroll told another member that the desert exercise was a dry run for the New Year’s Eve attack.

“What we’re doing will be considered a terrorist act,” she said, according to the affidavit.

At the site, they pitched tents and set up tables. They laid out PVC pipes, charcoal, sulfur, gasoline, string, cloth, and protective gear. As they began assembling the devices, the FBI moved in. Overhead, an FBI surveillance plane recorded the scene as agents took into custody four alleged members of the Turtle Island Liberation Front including Carroll and Page, along with Tina Lai and Dante Gaffield. (An attorney for Page declined to comment, and lawyers for Gaffield and Lai did not immediately respond.)

Nonpartisan Incentive Structure”

Terrorism prosecutions built around confidential informants have long drawn criticism, particularly over the risk of entrapment.

For more than a decade, legal scholars have argued that while these cases often resemble classic government inducement, they rarely meet the legal standard for entrapment. Courts define predisposition so broadly that ideological sympathy or recorded rhetoric is treated as evidence of a preexisting willingness to commit violence — a framework that effectively shields government-manufactured plots from meaningful judicial scrutiny.

That concern surfaced starkly in a previous sting operation involving the so-called Newburgh Four , in which an aggressive and prolific FBI informant steered four poor Black men into a scheme to bomb synagogues and attack an Air Force base. Years later, a federal judge granted the men compassionate release , describing the case as an “FBI-orchestrated conspiracy.”

Because informants can be so instrumental in building cases, their use can be leveraged by authorities to focus resources on investigations with more political overtones.

At times, the right has criticized the political nature of some cases. Among them was the case in which the FBI encouraged a plot to kidnap Michigan Gov. Gretchen Whitmer — a sting that the FBI’s Patel and Bongino harshly criticized back when they spent their days attached to the microphones of right-wing podcasts.

“There is a nonpartisan incentive structure that has become overly reliant on these kinds of confidential human sources,” said Crowder.

Crowder knows better than most. In 2008, he and fellow activist David McKay were arrested and charged with plotting to use Molotov cocktails at the Republican National Convention in Saint Paul, Minnesota. Despite deciding not to follow through with the plan, both ultimately pleaded guilty, with Crowder sentenced to two years in prison and McKay to four.

Part of the playbook, Crowder said, is for an informant to exploit their targets’ “righteous anger.”

The case against Crowder and McKay case hinged on the work of an FBI informant, Brandon Darby, who had been a prominent activist in anarchist circles in Texas and Louisiana. Crowder and McKay looked up to Darby, viewing him as a mentor and someone they hoped to impress or convince of their radical bona fides. In interviews over the years, they’ve alleged that Darby — who now works at Breitbart — was instrumental to their decision to cross the line from protest to discussing something more violent.

Part of the playbook, Crowder said, is for an informant to exploit their targets’ “righteous anger” — in the case of the Turtle Bay Liberation Front, rights violations in Palestine and ICE actions in Los Angeles. From there, authorities take advantage of the allege plotters’ political immaturity, walking hand in hand with them as they cross the line from legal dissent into illegal conspiracy.

The informant gets paid, the FBI gets a good headline that justifies their anti-terrorism budget, and the defendants are left to face the consequences, often without ever posing a real threat to public safety, Crowder said.

“On both sides you have a sort of momentum that develops,” Crowder said. “This ICE repression is crazy, and that feeds into a sort of hopelessness that drives a sort of nihilistic response that you see from people who have immature politics. And then that heartfelt but immature and irresponsible response plays into the incentive structure of the FBI.”

Christian Kastner: Simple-PPA, a minimalistic PPA implementation

PlanetDebian
www.kvr.at
2025-12-16 20:23:05
Today, the Debusine developers launched Debusine repositories, a beta implementation of PPAs. In the announcement, Colin remarks that "[d]iscussions about this have been happening for long enough that people started referring to PPAs for Debian as 'bikesheds'"; a characterization that I'm sure most ...
Original Article

Today, the Debusine developers launched Debusine repositories , a beta implementation of PPAs. In the announcement, Colin remarks that "[d]iscussions about this have been happening for long enough that people started referring to PPAs for Debian as 'bikesheds'" ; a characterization that I'm sure most will agree with.

So it is with great amusement that on this same day, I launch a second PPA implementation for Debian: Simple-PPA .

Simple-PPA was never meant to compete with Debusine, though. In fact, it's entirely the opposite: from discussions at DebConf, I knew that it was only a matter of time until Debusine gained a PPA-like feature, but I needed a stop-gap solution earlier, and with some polish, what was once by Python script already doing APT processing for apt.ai.debian.net , recently became Simple-PPA.

Consequently, Simple-PPA lacks (and will always lack) all of the features that Debusine offers: there is no auto-building, no CI, nor any other type of QA. It's the simplest possible type of APT repository: you just upload packages, they get imported into an archive, and the archive is exposed via a web server. Under the hood, reprepro does all the heavy lifting.

However, this also means it's trivial to set up. The following is the entire configuration that simple-ppa.debian.net started with:

# simple-ppa.conf

[CORE]
SignWith = 2906D748B7551BC8
ExportDir = /srv/www/simple-ppa
MailFrom: Simple-PPA <admin@simple-ppa.debian.net>
Codenames = sid forky trixie trixie-backports bookworm bookworm-backports
AlsoAllow = forky: unstable
            trixie: unstable
            bookworm: unstable

[simple-ppa-dev]
Label = Simple-PPA's self-hosted development repository
# ckk's key
Uploaders = allow * by key E76004C5CEF0C94C+

[ckk]
Label = Christian Kastner at Simple-PPA
Uploaders = allow * by key E76004C5CEF0C94C+

The CORE section just sets some defaults and sensible rules. Two PPAs are defined, simple-ppa-dev and ckk , which accept packages signed by the key with the ID E76004C5CEF0C94C . These PPAs use the global defaults, but individual PPAs can override Architectures , Suites , and Components , and of course allow an arbitrary number of users.

Users upload to this archive using SFTP (e.g.: with dput-ng ). Every 15 minutes, uploads get processed, with ACCEPTED or REJECTED mails sent to the Maintainer address. The APT archive of all PPAs is signed with a single global key.

I myself intend to use Debusine repositories soon, as the autobuilding and the QA tasks Debusine offers are something I need. However, I do still see a niche use case for Simple-PPA: when you need an APT archive, but don't want to do a deep dive into reprepro (which is extremely powerful).

If you'd like to give Simple-PPA a try, head over to simple-ppa.debian.net and follow the instructions for users.

Amazon disrupts Russian GRU hackers attacking edge network devices

Bleeping Computer
www.bleepingcomputer.com
2025-12-16 20:13:09
The Amazon Threat Intelligence team has disrupted active operations attributed to hackers working for the Russian foreign military intelligence agency, the GRU, who targeted customers' cloud infrastructure. [...]...
Original Article

Amazon disrupts Russian GRU hackers attacking edge network devices

The Amazon Threat Intelligence team has disrupted active operations attributed to hackers working for the Russian foreign military intelligence agency, the GRU, who targeted customers' cloud infrastructure.

The cloud services provider observed a focus on Western critical infrastructure, especially the energy sector, in activity that started in 2021.

Over time, the threat actor pivoted from exploiting vulnerabilities (zero-days and known ones) to leveraging misconfigured edge devices for initial access.

Wiz

Fewer vulnerabilies exploited

CJ Moses, the CISO of Amazon Integrated Security, notes that up to 2024, the "years-long" campaign exploited multiple vulnerabilities in WatchGuard, Confluence, and Veeam as the primary initial access vector and targeted misconfigured devices.

This year, though, the threat actor relied less on vulnerabilities and more on targeting misconfigured customer network edge devices, such as enterprise routers, VPN gateways, network management appliances, collaboration platforms, and cloud-based project management solutions.

"Targeting the 'low-hanging fruit' of likely misconfigured customer devices with exposed management interfaces achieves the same strategic objectives, which is persistent access to critical infrastructure networks and credential harvesting for accessing victim organizations’ online services," Moses explains .

"The threat actor’s shift in operational tempo represents a concerning evolution: while customer misconfiguration targeting has been ongoing since at least 2022, the actor maintained sustained focus on this activity in 2025 while reducing investment in zero-day and N-day exploitation," he added.

However, the tactical evolution did not reflect any change in the group’s operational objectives: stealing credentials and moving laterally on the victim network with as little exposure and as few resources as possible.

Based on targeting patterns and overlaps in infrastructure seen in attacks from Sandworm (APT44, Seashell Blizzard) and Curly COMrades, Amazon assesses with high confidence that the observed attacks were carried out by hackers working for the Russian GRU.

Amazon believes that the Curly COMRades hackers, first reported by Bitdefender , may be tasked with post-compromise activity in a  broader GRU campaing involving multiple specialized subclusters.

Spreading on the network

Although Amazon did not directly observe the extraction mechanism, evidence in the form of delays between device compromise and leveraging the credentials, and abuse of organization credentials, points to passive packet capturing and traffic interception.

Compromised devices were customer-managed network appliances hosted on AWS EC2 instances, and Amazon noted that the attacks did not leverage flaws on the AWS service itself.

After discovering the attacks, Amazon took immediate action to protect compromised EC2 instances and notified affected customers of the breach. Moreover, they shared intelligence with impacted vendors and industry partners.

"Through coordinated efforts, since our discovery of this activity, we have disrupted active threat actor operations and reduced the attack surface available to this threat activity subcluster," Amazon said.

Amazon has shared the offending IP addresses in its report but warned not to block them without first conducting a contextual investigation because they are legitimate servers that the threat actor compromised to proxy its traffic.

The company further recommended a series of “immediate priority actions” for next year, such as auditing network devices, watching for credential replay activity, and monitoring access to administrative portals.

In AWS environments specifically, it is recommended to isolate management interfaces, restrict security groups, and enable CloudTrail, GuardDuty, and VPC Flow Logs.

tines

Break down IAM silos like Bitpanda, KnowBe4, and PathAI

Broken IAM isn't just an IT problem - the impact ripples across your whole business.

This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

Mozilla gets a new CEO: Anthony Enzor-DeMeo

Linux Weekly News
lwn.net
2025-12-16 20:09:56
Mozilla has announced a new CEO, Anthony Enzor-DeMeo. Prior to becoming CEO, Enzor-DeMeo was general manager of Firefox and led its "vision, strategy, and business performance". He has published a blog post about taking over from interim CEO Laura Chambers, and his plans for Mozilla and Firefox: A...
Original Article

Mozilla has announced a new CEO, Anthony Enzor-DeMeo. Prior to becoming CEO, Enzor-DeMeo was general manager of Firefox and led its " vision, strategy, and business performance ". He has published a blog post about taking over from interim CEO Laura Chambers, and his plans for Mozilla and Firefox:

As Mozilla moves forward, we will focus on becoming the trusted software company. This is not a slogan. It is a direction that guides how we build and how we grow. It means three things.

  • First: Every product we build must give people agency in how it works. Privacy, data use, and AI must be clear and understandable. Controls must be simple. AI should always be a choice — something people can easily turn off. People should know why a feature works the way it does and what value they get from it.
  • Second: our business model must align with trust. We will grow through transparent monetization that people recognize and value.
  • Third: Firefox will grow from a browser into a broader ecosystem of trusted software. Firefox will remain our anchor. It will evolve into a modern AI browser and support a portfolio of new and trusted software additions.

How Mayor Mamdani Can Revive NYC's Most Important Climate Law

hellgate
hellgatenyc.com
2025-12-16 20:09:22
New York City's signature climate law needs someone to actually enforce it. Here's how incoming Mayor Mamdani can hit the ground running....
Original Article

Mayor Bill de Blasio's biggest climate accomplishment was to preside over a set of laws that targeted the city's greatest contributor to greenhouse gas emissions: Buildings .

Known as Local Law 97 , the regulations were designed to force big office buildings and smaller residential buildings to electrify their heating, cooling, and cooking, so that by the year 2050, they would lower their carbon emissions from 2005 levels by 80 percent.

But since Mayor Eric Adams took office, large office buildings ( many owned by contributors to Adams ) have been granted extensions and leniency when it comes to getting off of fossil fuels or making environmental upgrades, while large residential co-ops are staring down deadlines to begin energy-saving measures and electric heating conversions many say they can't remotely pay for .

During the campaign, Zohran Mamdani said he'd try to revive Local Law 97 implementation by working with the state to extend the J-51 tax break , which lets co-op owners deduct climate improvement costs from their property tax bills, and he'd also use the city's own purchasing power to more affordably buy thousands of electric heat pumps to then be resold to building owners at cost.

Give us your email to read the full story

Sign up now for our free newsletters.

Sign up

Typefaces for Dyslexia

Daring Fireball
adrianroselli.com
2025-12-16 19:58:17
I dare say this post from Adrian Roselli — first published in 2015 and updated 16 times (and counting) since — is the definitive debunking of the pseudoscience claims regarding deliberately ugly fonts being somehow beneficial to readers with dyslexia.  ★  ...
Original Article
Example showing the letterforms of b, p, and d, and how they have a thicker stroke on the bottom.
Both typefaces claim that heavier strokes on the bottom prevent dyslexic readers from flipping the letters when viewing them. The original caption: A heavier bottom is used to show which way is supposed to be down.

I’ve been writing this post in fits, so it may be a bit disjointed. I started it on my flight home from CSUN, and continued to work on it on subsequent flights. Apologies if it’s a bit chaotic.

TL;DR : Typefaces designed to help dyslexics have no effect.

I’ll list information about the two typefaces that I am aware of (which are designed explicitly for readers with dyslexia), as well as notes from the talk at CSUN and a couple other examples.

Typefaces

I am aware of two typefaces that are designed with dyslexic readers in mind.

OpenDyslexic

Open Dyslexic is an open source typeface for readers with dyslexia. The rationale behind the design:

OpenDyslexic is created to help with some of the symptoms of dyslexia. Letters have heavy weighted bottoms to indicate direction. You are able to quickly figure out which part of the letter is down which aids in recognizing the correct letter, and sometimes helps to keep your brain from rotating them around. Consistently weighted bottoms can also help reinforce the line of text. The unique shapes of each letter can help prevent confusion through flipping and swapping.

Dyslexie

Dyslexie is a paid typeface (free for home use). The site references research that supports the following claim:

Representative research among many dyslectics has shown that the font Dyslexie actually helps them with reading texts faster and with fewer errors.

I would like to note that copying that text directly from the browser wasn’t easy. The use of Cufon to embed the typeface drops each word into its own element that itself hides and replaces the raw text in a canvas element. I’m sure you can imagine how much that offends me.

The following video explains the idea behind the typeface:

Vimeo: Dyslexie Font , 0:59

Study: Can a font improve reading?

The latest study to suggest that typefaces designed to aid reading for dyslexics had little to no effect was presented at CSUN this past week. As I noted on Twitter, I already had an idea what the results would be, and I came away feeling validated.

The study hasn’t been pubished yet and I saw its first general presentation. The study was conducted at Mount Allison University, a 2,500 student college with 215 full-time students with disabilities. 50% of those students are classified as having a learning disability.

The questions asked by the study:

  • Do the style of the letters on a page mean that you read faster and make fewer errors?
  • Do persons with LD [learning disabilities] using this font read faster and make fewer errors?

The typefaces (Open Dyslexic and Dyslexie) make claims about their benefits, aggregated in the presentation as:

  • Students with surface dyslexia experience letters flipping and moving around; Letters needed to be bottom heavy to prevent them from moving around
  • New font would increase reading speed
  • Will also increase accuracy (fewer errors)
  • Will decrease reading stress
  • Widely promoted to on-line uses and in word processing (Instapaper, iPad, an app)
  • Strong anecdotal feedback

The presenter outlined some literature references, the procedure the team followed to perform the study, the nature of the participants (and control group), and the overall results.

The first bullet in the summary wraps it up nicely:

  • The font does NOT improve reading speed or accuracy for students with LD.

An interesting note from the study was that half of each group (50% of control, 57% of LD group) said they would consider using the font and were then shown how to access it (download and install it, which I assume was Open Dyslexic). In a follow-up, none of those participants were using the font.

Another interesting point was that 40% of the control group and 48% of the LD group thought they performed better when using Open Dyslexic, though that was not the case.

As anyone who’s done user testing knows, it’s not uncommon for users to report one thing while doing or thinking another, so I consider this to be anecdotal reinforcement that the typeface had no benefit for users.

Study: Good Fonts for Dyslexia: An Experimental Study

In late 2013 I found a write-up on a Spanish study that reviewed which fonts were easiest for readers with dyslexia. The post summarizes the study:

Based on the evaluation of 48 dyslexic subjects ages 11-50, reading 12 texts with 12 different fonts, they determined that reading performance was best with sans serif, monospaced, and roman fonts used in the study. They also found that reading was significantly impaired when italic fonts were used.

[…]

Use of the OpenDyslexic font did not enhance text readability or reading speed. The study participants strongly preferred Verdana or Helvetica over the OpenDyslexic alternative.

You can find the full text of the study in a PDF file on the site for the Natural Language Processing group of the Department of Information and Communication Technologies at Pompeu Fabra University.

General Tips

For those of us who build applications and sites with content of any length (whether instructions for shopping carts or rant-laden long-form articles), I have found a few techniques are generally agreed upon by the community (feedback is welcome!):

  • Avoid justified text.
  • Use generous line spacing / leading.
  • Use generous letter spacing.
  • Avoid italics.
  • Generally use sans serif faces.
  • Use larger text.
  • Use good contrast.
  • Use clear, concise writing.

This generally follows rules for good typography.

You may have heard that Comic Sans is easier for readers with dyslexia to understand, but so far that evidence appears to be anecdotal. Certainly not enough to warrant punishing all your other users.

If you read an article that suggests users with dyslexia see letters flip or rotate, then be wary. Not only was this assertion challenged by participants in the study reported at CSUN, but generally the participant reaction was anger. The flipping/rotating may be a myth perpetuated by those without dyslexia in an effort to make sense of its effects.

Update: March 26, 2015

In a post from 2011 ( Dyslexia, Fonts & Open Source ), Mike Gifford outlines some of the issues related to supporting readers with dyslexia, including typefaces.

Update: April 17, 2015

Neil Milliken notes that, as someone with dyslexia, he finds the custom dyslexic typefaces unhelpful and unattractive.

Update: June 5, 2015

Chuck Bigelow, creator of the Lucida Family, wrote the following back in November:

In preparing a literature review on dyslexia and typography for a major font vendor, I surveyed more than fifty scientific papers and books about dyslexia, paying special attention to those with typographic relevance. In the scientific literature, I found no evidence that special dyslexia fonts confer statistically significant improvements in reading speed compared to standard, run-of-the-mill fonts.

Some readers disagree with his assertions in comments on a Fast Company post covering his original post.

Update: July 10, 2015

There are users who get benefits from the typefaces. As expected, different people will have different results. Seren D (who also tells us of problems in icon fonts ) explains:

@aardrian I find it really helpful. I find everything flows nicers and I can tell what each letter is and don't loose track of where I am

Update: December 6, 2016

Today A List Apart posted a new article, Accessibility Whack-A-Mole , that discusses a process of tweaking an existing typeface and testing it with users. It includes many tips not just for letterform adjustments, but also for layout and flow.

Update: February 28, 2017

There is a post circulating with the unfortunate title Hating Comic Sans Is Ableist . The thrust of the article is that the author’s sister, who has dyslexia, discovered her reading comprehension improved greatly when she used Comic Sans. From there the author accuses everyone who dislikes Comic Sans of lacking empathy and being ableist.

Comic Sans is ugly (to me, and quite a lot of people), as are all the other typefaces designed specifically for dyslexia. That dislike is not ableist. Making fun of someone who uses it for reading comprehension would be ableist. Embedding images in an article on a platform that does not support alternative text without providing a plain text description is ableist. Just for context, that is.

Update: March 5, 2017

At this year’s CSUN conference Gareth Ford Williams presented What Makes One Font More Accessible than Another? (that links just to the abstract, no slides are online yet). To distill the gist of his talk, he confirmed that no single typeface works for all users, though there are some common traits that help many. Traits such as letter shape, bowl size, similarities between mirrored letters, and so on. He also confirmed that pre-existing familiarity with a typeface matters. Finally, good typographic practices are a huge factor.

Update: September 5, 2017

In the post Fonts don’t matter , not much effort is given to arguing why fonts don’t matter. Instead the post addresses what you can do in your layout that is more important for readability than choosing a typeface. You could basically skip the General Tips section above and read that post instead.

Update: October 7, 2017

There is another typeface that has been around for a bit that I had no idea existed. I can only hope it is never being forced on users in lieu of good typography.

Dyslexic friendly font github.com/Orange-OpenSou… #opensource #accessibility #parisweb

Update: October 12, 2017

Accessible type selection is more important than ever. Here's how to master it. creativebloq.com/…accessible-web-typography

This over-complicates, pitches: twitter.com/netmag/…
*sigh* Do not use an illegible typeface, then good typesetting is more important.

Update: August 14, 2020

Gareth Ford Williams has written a great overview about how to choose typefaces that I highly recommend you read before you even consider a dyslexia-specific typeface: A Guide to Understanding What Makes a Typeface Accessible, and How to Make Informed Decisions. (the period is in the title, so don’t at-me)

He includes links to academic papers, typography resources, books, literacy reports, and so on. Those who know me well also know that I rail against anything about accessibility that is posted to Medium, but the information is solid and he has taken care to use good alt text.

Update: August 19, 2020

Over at The Cut is a brief article with an unfortunate title: The Reason Comic Sans Is a Public Good .

From the assertion in the title it spends half the article (two paragraphs) repeating a 2017 post claiming disliking Comic Sans is ableist (see my February 2017 update above on why that is absurd). As supporting evidence in the final paragraph we get:

To wit, Comic Sans is recommended by the British Dyslexia Association and the Dyslexia Association of Ireland . An American Institute of Graphic Arts post from last summer said that it might be the best font for dyslexics […]

Except that entire paragraph is bunk.

  • The linked British Dyslexia Association page does not recommend it. The page mentions studies, acknowledges none specifically looked at typefaces, and even mentioned a survey of its users (few responded).
  • The Dyslexia Association of Ireland site is down for maintenance (was it down when the article was written?), but the most recent version in the Wayback lists the fonts Arial, Comic Sans, Verdana, and Sassoon as options, while providing 30 more practical tips around layout, structure, and content.
  • The 2016 AIGA post (which is structured as an interview with an unnamed interviewee) doesn’t even mention Comic Sans until the last paragraph as a throwaway reference (with no link) to a passing anecdotal mention at Dyslexic.com.

And that is the entirety of the evidence supporting Comic Sans. Go read Gareth’s post instead: A Guide to Understanding What Makes a Typeface Accessible, and How to Make Informed Decisions.

Update: January 22, 2021

Another round-up of research confirms Comic Sans is not a boon:

So there is agreement, of a sort, between the typographers and the dyslexia researchers: spacing, not letter shape, is key. However, all the researchers in this area stress more research is needed.

[…]

The big question of this article, then, has a clear answer: Comic Sans use should not be justified by claims of increased readability or benefits to dyslexic students or indeed for handwriting, but if you just like it, and your pupils like it, there is no good reason you should not use it. Or not use most other fonts for that matter. Font choice, it seems, is the least of your worries.

As usual, a single technology (a typeface) is not a quick fix for such a broad need. People need to do the work (of typesetting in this case) to really help other people.

Update: December 15, 2021

A well-intentioned article at Smashing Magazine has put forth some suggestions for supporting readers with dyslexia: Adding A Dyslexia-Friendly Mode To A Website .

It makes some suggestions that seem to only be backed up by anecdata, small sample sizes, or assumptions. It uses WCAG to justify some of its arguments. It also suggests a “dyslexia-friendly mode”. Finally, it echoes a preference for Comic Sans without backing it up in any way. In short, it may end up perpetuating myths instead of getting people to think critically about supporting users.

Gareth Ford Williams left an extensive 13 point comment (Smashing’s comment system combined 4 of them) addressing many of the assertions raised in the post. Sadly, because Smashing’s comments are both collapsed by default and have no unique IDs, it is impossible to link directly to it by anchor or text fragment (yes, I pinged Smashing about this ). So go to the comment section , activate the “Load all…” button, and scroll down to Gareth’s comment dated December 14, 2021 (there is another earlier comment by a different Gareth). Smashing Magazine recently updated its commenting system to allow direct links to comments.

Gareth also wrote a post on LinkedIn, Dyslexic Myths Presented as Truths . Sadly, since it is LinkedIn, if you want to see all the comments on Gareth’s post you need to have an account and be logged in. And if you find LinkedIn’s WCAG-failing non-underlined links impossible to identify, you can run my underline bookmarklet .

Update: May 2, 2023

DysTtitles sample showing numbers, punctuation, and full alphabet in upper and lower-case letters. Ads of the World profiled a new typeface designed for use in video captions to benefit dyslexic viewers:

CANAL+, working closely with ad agency BETC Paris and NGO Puissance Dys (created in 1992 by Beatrice Sauvegeot and Dr. Jean Metellus with the ambition of helping dyslexic people) has come up with a solution for all these people – 8 to 12% of the world’s population – and is introducing DYSTITLES: subtitles adapted for reading for dyslexic and non-dyslexic people.

Beatrice Sauveagot, speech therapist and neuropsychologist, President of Puissance Dys, has spent the last ten years developing a font adapted for dyslexic people. Based on this initial research, BETC and Puissance Dys created a new font that can be read by everyone. Specifically created for reading subtitles, the unique design of these characters play with depth and forms to allow dyslexic people to read without having to decipher words letter by letter and is totally readable by non-dyslexic people after a small adaptation time.

An advertising industry site is not likely to provide links to the supporting research or material. While the French video on the page discusses the letterforms, without closed captions or subtitles (yes, irony) I have no idea if it is citing any particular research.

I went to the web site for Puissance Dys to see if I could dig up some research. I found testimonials, press, a dyslexia diagnosis app, internship info, and a link to its overall venture . I found no research, though it may be a function of me not speaking French and auto translation leading me astray.

While some folks may find the typeface (used in subtitles or elsewhere) helpful, its creator asserting it can be read by everyone […] after a small adaptation time is a bold statement that warrants justification. I was unable to find any.

The home page offers a feature to swap the text on the page into the custom typeface. What follows is a comparison. I leave it to you to decide if the typeface is helpful and/or how long you feel it might take to adapt.

Puissance Dys home page. Puissance Dys home page with the text showing using the Puissance Dys custom typeface.
Content on the PuissanceDys.org home page before and after swapping the typeface. Bear in mind this page went through automated translation from French to English.

If LinkedIn is your bag, Gareth Ford Williams has shared his opinion .

Update: October 21, 2025

I keep forgetting to link this one from nine years ago:

Given the press and popular support of using a specialized font as a remedy for dyslexia, it is critical to highlight that results from this study failed to identify any positive effect for using it. Currently, there is no documentation to support a specialized font is an evidence-based practice.

Oh, and also this one:

Results showed that low-progress readers performed better (i.e., read 7% more words per minute) in Dyslexie font than in standardly spaced Arial font. However, when within-word spacing and between-word spacing of Arial font was matched to that of Dyslexie font, the difference in reading speed was no longer significant. We concluded that the efficacy of Dyslexie font is not because of its specially designed letter shapes, but because of its particular spacing settings.

These were a year after I wrote this post and so far I’ve seen nothing refute these kinds of study results. Then ongoing lesson seems clear — start with better typography and then look at typeface changes.

Zara Picken’s ‘Modern Illustration’

Daring Fireball
www.modernillustration.org
2025-12-16 19:39:44
Modern Illustration is a project by illustrator Zara Picken, featuring print artefacts from her extensive personal collection. Her aim is to preserve and document outstanding examples of mid-20th century commercial art, creating an accessible resource for understanding illustration history. Glo...
Original Article

An archive of illustration from c.1950-1975, shining a spotlight on pioneering illustrators and their work.

Modern Illustration is a project by illustrator Zara Picken , featuring print artefacts from her extensive personal collection. Her aim is to preserve and document outstanding examples of mid-20th century commercial art, creating an accessible resource for understanding illustration history.

Recent Additions

Archive

Format: Bookmark

Year: c.1950s

Format: Bookmark

Year: 1959

Format: Beermat

Year: c.1960s

Format: Matchbox Label

Year: c.1960

Format: Playing Card

Year: 1958

Format: Matchbox Label

Year: 1955

Format: Booklet

Year: c.1960s

Format: Matchbox Label

Year: 1959

Format: Leaflet

Year: 1962

Format: Exercise book cover

Year: c.1952

Format: Matchbox Labels

Year: c.1960s

Format: Matchbook

Year: c.1959

No Graphics API

Hacker News
www.sebastianaaltonen.com
2025-12-16 19:20:17
Comments...
Original Article

Introduction

My name is Sebastian Aaltonen. I have been writing graphics code for 30 years. I shipped my first 3d accelerated game in 1999. Since then I have been working with almost every gaming console generation (Nokia N-Gage, Nintendo DS/Switch, Sony Playstation/Portable, Microsoft Xbox) and every PC graphics API (DirectX, OpenGL, Vulkan). For the last 4 years I have been building a new renderer for HypeHype targeting WebGPU, Metal (Mac & iOS) and Vulkan (Android). During my career I have been building several Ubisoft internal engines, optimizing Unreal Engine 4 and leading the Unity DOTS graphics team. I am a member of the Vulkan Advisory Panel and an Arm Ambassador.

This blog post includes lots of low level hardware details. When writing this post I used “GPT5 Thinking” AI model to cross reference public Linux open source drivers to confirm my knowledge and to ensure no NDA information is present in this blog post. Sources: AMD RDNA ISA documents and GPUOpen, Nvidia PTX ISA documents, Intel PRM, Linux open source GPU drivers (Mesa, Freedreno, Turnip, Asahi) and vendor optimization guides/presentations. The blog post has been screened by several industry insiders before the public release.

Low-level graphics APIs change the industry

Ten years ago, a significant shift occurred in real-time computer graphics with the introduction of new low-level PC graphics APIs. AMD had won both Xbox One (2013) and Playstation 4 (2013) contracts. Their new Graphics Core Next (GCN) architecture became the de-facto lead development platform for AAA games. PC graphics APIs at that time, DirectX 11 and OpenGL 4.5, had heavy driver overhead and were designed for single threaded rendering. AAA developers demanded higher performance APIs for PC. DICE joined with AMD to create a low level AMD GCN specific API for the PC called Mantle. As a response, Microsoft, Khronos and Apple started developing their own low-level APIs: DirectX 12, Vulkan and Metal were born.

The initial reception of these new low-level APIs was mixed. Synthetic benchmarks and demos showed substantial performance increases, but performance gains couldn’t be seen in major game engines such as Unreal and Unity. At Ubisoft, our teams noticed that porting existing DirectX 11 renderers to DirectX 12 often resulted in performance regression. Something wasn’t right.

Existing high-level APIs featured minimal persistent state, with fine-grained state setters and individual data inputs bound to the shader just prior to draw call submission. New low-level APIs aimed to make draw calls cheaper by ahead-of-time bundling shader pipeline state and bindings into persistent objects. GPU architectures were highly heterogeneous back in the day. Doing the data remapping, validation, and uploading ahead of time was a big gain. However, the rendering hardware interfaces (RHI) of existing game engines were designed for fine grained immediate mode rendering, while the new low-level APIs required bundling data in persistent objects.

To address this incompatibility, a new low-level graphics remapping layer grew beneath the RHI. This layer assumed the complexity previously handled by the OpenGL and DirectX 11 graphics drivers, tracking resources and managing mappings between the fine-grained dynamic user-land state and the persistent low-level GPU state. Graphics programmers started specializing into two distinct roles: low-level graphics programmers, who focused on the new low-level “driver” layer and the RHI, and high-level graphics programmers, who built visual graphics algorithms on top of the RHI. Visual programming was also getting more complex due to physically based lighting models, compute shaders and later ray-tracing.

Modern APIs?

DirectX 12, Vulkan, and Metal are often referred to as “modern APIs”. These APIs are now 10 years old. They were initially designed to support GPUs that are now 13 years old, an incredibly long time in GPU history. Older GPU architectures were optimized for traditional vertex and pixel shader tasks rather than the compute-intensive generic workloads prevalent today. They had vendor specific binding models and data paths. Hardware differences had to be wrapped under the same API. Ahead-of-time created persistent objects were crucial in offloading the mapping, uploading, validation and binding costs.

In contrast, the console APIs and Mantle were exclusively designed for AMD's GCN architecture, a forward-thinking design for its time. GCN boasted a comprehensive read/write cache hierarchy and scalar registers capable of storing texture and buffer descriptors, effectively treating everything as memory. No complex API for remapping the data was required, and significantly less ahead-of-time work was needed. The console APIs and Mantle had much less API complexity due to targeting a single modern GPU architecture.

A decade has passed, and GPUs have undergone a significant evolution. All modern GPU architectures now feature complete cache hierarchies with coherent last-level caches. CPUs can write directly to GPU memory using PCIe REBAR or UMA and 64-bit GPU pointers are directly supported in shaders. Texture samplers are bindless, eliminating the need for a CPU driver to configure the descriptor bindings. Texture descriptors can be directly stored in arrays within the GPU memory (often called descriptor heaps). If we were to design an API tailored for modern GPUs today, it wouldn’t need most of these persistent “retained mode” objects. The compromises that DirectX 12.0, Metal 1 and Vulkan 1.0 had to make are not needed anymore. We could simplify the API drastically.

The past decade has revealed the weaknesses of the modern APIs. The PSO permutation explosion is the biggest problem we need to solve. Vendors (Valve, Nvidia, etc) have massive cloud servers storing terabytes of PSOs for each different architecture/driver combination. User's local PSO cache size can exceed 100GB. No wonder the gamers are complaining that loading takes ages and stutter is all over the place.

The history of GPUs and APIs

Before we talk about stripping the API surface, we need to understand why graphics APIs were historically designed this way. OpenGL wasn't intentionally slow, nor was Vulkan intentionally complex. 10-20 years ago GPU hardware was highly diverse and undergoing rapid evolution. Designing a cross-platform API for such a diverse set of hardware required compromises.

Let’s start with a classic: The 3dFX Voodoo 2 12MB (1998) was a three chip design: A single rasterizer chip connected to a 4MB framebuffer memory and two texture sampling chips, each connected to their own 4MB texture memory. There was no geometry pipeline and no programmable shaders. CPU sent pre-transformed triangle vertices to the rasterizer. The rasterizer had a configurable blending equation to control how the vertex colors and the two texture sampler results were combined together. Texture samplers could not read each-other’s memory or the framebuffer. Thus there was no support for multiple render passes. Since the hardware was incapable of window composition, it had a loopback cable to connect your dedicated 2d video card. 3d rendering only worked in exclusive fullscreen mode. A 3d graphics card was a highly specialized piece of hardware, with little in common with the current GPUs and their massive programmable SIMD arrays. Hardware of this era had a massive impact on DirectX (1995) and OpenGL (1992) design. Backwards compatibility played a huge role. APIs improved iteratively. These 30 year old API designs still impact the way we write software today.

3dFX Voodoo 2 12MB (1998): Individual processors and traces between them and their own memory chips (four 1MB chips for each processor) are clearly visible. Image © TechPowerUp.

Nvidia’s Geforce 256 coined the term GPU. It had a geometry processor in addition to the rasterizer. The geometry processor, rasterizer and texture sampling units were all integrated in the same die and shared memory. DirectX 7 introduced two new concepts: render target textures and uniform constants. Multipass rendering meant that texture samplers could read the rasterizer output, invalidating the 3dFX Voodoo 2 separate memory design.

The geometry processor API featured uniform data inputs for transform matrices (float4x4), light positions, and colors (float4). GPU implementations varied among manufacturers, many opting to embed a small constant memory block within the geometry engine. But this wasn’t the only way to do it. In the OpenGL API each shader had its own persistent uniforms. This design enabled the driver to embed constants directly in the shader's instruction stream, an API peculiarity that still persists in OpenGL 4.6 and ES 3.2 today.

GPUs back then didn’t have generic read & write caches. Rasterizer had screen local cache for blending and depth buffering and texture samplers leaned on linearly interpolated vertex UVs for data prefetching. When shaders were introduced in DirectX 8 shader model 1.0 (SM 1.0), the pixel shader stage didn’t support calculating texture UVs. UVs were calculated at vertex granularity, interpolated by the hardware and passed directly to the texture samplers.

DirectX 9 brought a substantial increase in shader instruction limits, but shader model 2.0 didn’t expose any new data paths. Both vertex and pixel shaders still operated as 1:1 input:output machines, allowing users to only customize the transform math of the vertex position and attributes and the pixel color. Programmable load and store were not supported. The fixed-function input blocks persisted: vertex fetch, uniform (constant) memory and texture sampler. Vertex shader was a separate execution unit. It gained new features like the ability to index constants (limited to float4 arrays) but still lacked texture sampling support.

DirectX 9 shader model 3.0 increased the instruction limit to 65536 making it difficult for humans to write and maintain shader assembly anymore. Higher level shading languages were born: HLSL (2002) and GLSL (2002-2004). These languages adapted the 1:1 elementwise transform design. Each shader invocation operated on a single data element: vertex or pixel. Framework-style shader design heavily affected the graphics API design in the following years. It was a nice way to abstract hardware differences back in the day, but is showing scaling pains today.

DirectX 11 was a significant shift in the data model, introducing support for compute shaders, generic read-write buffers and indirect drawing. The GPU could now fully feed itself. The inclusion of generic buffers enabled shader programs to access and modify programmable memory locations, which forced hardware vendors to implement generic cache hierarchies. Shaders evolved beyond simple 1:1 data transformations, marking the end of specialized, hardcoded data paths. GPU hardware started to shift towards a generic SIMD design. SIMD units were now executing all the different shader types: vertex, pixel, geometry, hull, domain and compute. Today the framework has 16 different shader entry points. This adds a lot of API surface and makes composition difficult. As a result GLSL and HLSL still don’t have a flourishing library ecosystem.

DirectX 11 featured a whole zoo of buffer types, each designed to accommodate specific hardware data path peculiarities: typed SRV & UAV, byte address SRV & UAV, structured SRV & UAV, append & consume (with counter), constant, vertex, and index buffers. Like textures, buffers in DirectX utilize an opaque descriptor. Descriptors are hardware specific (commonly 128-256 bit) data blobs encoding the size, format, properties and data address of the resource in GPU memory. DirectX 11 GPUs leveraged their texture samplers for buffer load (gather) operations. This was natural since the sampler already had a type conversion hardware and a small read-only data cache. Typed buffers supported the same formats as textures, and DirectX used the same SRV (shader resource view) abstraction for both textures and buffers.

The use of opaque buffer descriptors meant that the buffer format was not known at shader compile time. This was fine for read-only buffers as they were handled by the texture sampler. Read-write buffer (UAV in DirectX) was initially limited to 32-bit and 128-bit (vec4) types. Subsequent API and hardware revisions gradually addressed typed UAV load limitations, but the core issues persisted: a descriptor requires an indirection (contains a pointer), compiler optimizations are limited (data type is known only at runtime), format conversion hardware introduces latency (vs raw L1$ load), expand at load reserves registers for longer time (vs expand at use), descriptor management adds CPU driver complexity, and the API is complex (ten different buffer types).

In DirectX 11 the structured buffers were the only buffer type allowing an user defined struct type. All other buffer types represented a homogeneous array of simple scalar/vector elements. Unfortunately, structured buffers were not layout compatible with other buffer types. Users were not allowed to have structured buffer views to typed buffers, byte address buffers, or vertex/index buffers. The reason was that structured buffers had special AoSoA swizzle optimization under the hood, which was important for older vec4 architectures. This hardware specific optimization limited the structured buffer usability.

DirectX 12 made all buffers linear in memory, making them compatible with each other. SM 6.2 also added load<T> syntactic sugar for the byte address buffer, allowing clean struct loading syntax from arbitrary offset. All the old buffer types are still supported for backwards compatibility reasons and all the buffers still use opaque descriptors. HLSL is still missing support for 64-bit GPU pointers. In contrast, the Nvidia CUDA computing platform (2007) fully leaned on 64-bit pointers, but its popularity was initially limited to academic use. Today it is the leading AI platform and is heavily affecting the hardware design.

Support for 16-bit registers and 16-bit math was disorganized when DirectX 12 launched. Microsoft initially made a questionable decision to not backport DirectX 12 to Windows 7. Shader binaries targeting Windows 8 supported 16-bit types, but most gamers continued using Windows 7. Developers didn’t want to ship two sets of shaders. OpenGL lowp/mediump specification was also messy. Bit depths were not properly standardized. Mediump was a popular optimization in mobile games, but most PC drivers ignored it, making game developer’s life miserable. AAA games mostly ignored 16-bit math until PS4 Pro launched in 2016 with double rate fp16 support.

With the rise of AI, ray-tracing, and GPU-driven rendering, GPU vendors started focusing on optimizing their raw data load paths and providing larger and faster generic caches. Routing loads though the texture sampler (type conversion) added too much latency, as dependent load chains are common in modern shaders. Hardware got native support for narrow 8-bit, 16-bit, and 64-bit types and pointers.

Most vendors ditched their fixed function vertex fetch hardware, emitting standard raw load instructions in the vertex shader instead. Fully programmable vertex fetch allowed developers to write new algorithms such as clustered GPU-driven rendering. Fixed function hardware transistor budget could be used elsewhere.

Mesh shaders represent the culmination of rasterizer evolution, eliminating the need for index deduplication hardware and post-transform caches. In this paradigm, all inputs are treated as raw memory. The user is responsible for dividing the mesh into self-contained meshlets that internally share vertices. This process is often done offline. The GPU no longer needs to do parallel index deduplication for each draw call, saving power and transistors. Given that gaming accounts for only 10% of Nvidia's revenue today, while AI represents 90% and ray-tracing continues to grow, it is likely only a matter of time before the fixed function geometry hardware is stripped to bare minimum and drivers automatically convert vertex shaders to mesh shaders.

Mobile GPUs are tile-based renderers. Tilers bin the individual triangles to small tiles (commonly between 16x16 to 64x64 pixels) . Mesh shaders are too coarse grained for this purpose. Binning meshlets to tiny tiles would cause significant geometry overshading. There’s no clear convergence path. We still need to support the vertex shader path.

10 years ago when DirectX 12.0, Vulkan 1.0 and Metal 1.0 arrived, the existing GPU hardware didn’t widely support bindless resources. APIs adapted complex binding models to abstract the hardware differences. DirectX allowed indexing up to 128 resources per stage, Vulkan and Metal didn’t initially support descriptor indexing at all. Developers had to continue using traditional workarounds to reduce the bindings change overhead, such as packing textures into atlases and merging meshes together. The GPU hardware has evolved significantly during the past decade and converged to generic bindless SIMD design.

Let’s investigate how much simpler the graphics API and the shader language would become if we designed them solely for modern bindless hardware.

Modern GPU memory management

Let’s start our journey discussing memory management. Legacy graphics APIs abstracted the GPU memory management completely. Abstraction was necessary, as old GPUs had split memories and/or special data paths with various cache coherency concerns. When DirectX 12 and Vulkan arrived 10 years ago, the GPU hardware had matured enough to expose placement heaps to the user. Consoles had already exposed memory for a few generations and developers requested similar flexibility for PC and mobile. Apple introduced placement heaps 4 years after Vulkan and DirectX 12 in Metal 2.

Modern APIs require the user to enumerate the heap types to find out what kind of memory the GPU driver has to offer. It’s a good practice to preallocate memory in big chunks and suballocate it using a user-land allocator. However, there’s a design flaw in Vulkan: You have to create your texture/buffer object first. Then you can ask which heap types are compatible with the new resource. This forces the user into a lazy allocation pattern, which can cause performance hitches and memory spikes at runtime. This also makes it difficult to wrap a GPU memory allocation into a cross-platform library. AMD VMA, for example, creates both the Vulkan-specific buffer/texture object in addition to allocating memory. We want to fully separate these concerns.

Today the CPU has full visibility into the GPU memory. Integrated GPUs have UMA, and modern discrete GPUs have PCIe Resizable BAR. The whole GPU heap can be mapped. Vulkan heap API naturally supports CPU mapped GPU heaps. DirectX 12 got support in 2023 (HEAP_TYPE_GPU_UPLOAD).

CUDA has a simple design for GPU memory allocation: The GPU malloc API takes the size as input and returns a mapped CPU pointer. The GPU free API frees the memory. CUDA doesn’t support CPU mapped GPU memory. The GPU reads the CPU memory though the PCIe bus. CUDA also supports GPU memory allocations, but they can’t be directly written by the CPU.

We combine CUDA malloc design with CPU mapped GPU memory (UMA/ReBAR). It's the best of both worlds: The data is fast for the CPU to write and fast for the GPU to read, yet we maintain the clean, easy to use design.

// Allocate GPU memory for array of 1024 uint32
uint32* numbers = gpuMalloc(1024 * sizeof(uint32));

// Directly initialize (CPU mapped GPU pointer)
for (int i = 0; i < 1024; i++) numbers[i] = random();

gpuFree(numbers);

Default gpuMalloc alignment is 16 bytes (vec4 alignment). If you need wider alignment use gpuMalloc(size, alignment) overload. My example code uses gpuMalloc<T> wrapper, doing gpuMalloc(elements * sizeof(T), alignof(T)).

Writing data directly into GPU memory is optimal for small data like draw arguments, uniforms and descriptors. For large persistent data, we still want to perform a copy operation. GPUs store textures in a swizzled layout similar to Morton-order to improve cache locality. DirectX 11.3 and 12 tried to standardize the swizzle layout, but couldn’t get all GPU manufacturers onboard. The common way to perform texture swizzling is to use a driver provided copy command. The copy command reads linear texture data from a CPU mapped “upload” heap and writes to a swizzled layout in a private GPU heap. Every modern GPU also has lossless delta color compression (DCC). Modern GPUs copy engines are capable of DCC compression and decompression. DCC and Morton swizzle are the main reasons we want to copy textures into a private GPU heap. Recently, GPUs have also added generic lossless memory compression for buffer data. If the memory heap is CPU mapped, the GPU can’t enable vendor specific lossless compression, as the CPU wouldn’t know how to read or write it. A copy command must be used to compress the data.

We need a memory type parameter in the GPU malloc function to add support for private GPU memory. The standard memory type should be CPU mapped GPU memory (write combined CPU access). It is fast for the GPU to read, and the CPU can directly write to it just like it was a CPU memory pointer. GPU-only memory is used for textures and big GPU-only buffers. The CPU can’t directly write to these GPU pointers. The user writes the data to CPU mapped GPU memory first and then issues a copy command, which transforms the data to optimal compressed format. Modern texture samplers and display engines can read compressed GPU data directly, so there’s no need for subsequent data layout transforms (see chapter: Modern barriers). The uploaded data is ready to use immediately.

We have two types of GPU pointers, a CPU mapped virtual address and a GPU virtual address. The GPU can only dereference GPU addresses. All pointers in GPU data structures must use GPU addresses. CPU mapped addresses are only used for CPU writes. CUDA has an API to transform a CPU mapped address to a GPU address (cudaHostGetDevicePointer). Metal 4 buffer object has two getters: .contents (CPU mapped address) and .gpuAddress (GPU address). Since the gpuMalloc API returns a pointer, not a managed object handle (like Metal), we choose the CUDA approach (gpuHostToDevicePointer). This API call is not free. The driver likely implements it using a hash map (if other than base addresses need to be translated, we need a tree). Preferably we call the address translation once per allocation and cache in a user land struct (void *cpu, void *gpu). This is the approach my userland GPUBumpAllocator uses (see appendix for full implementation).

// Load a mesh using a 3rd party library
auto mesh = createMesh("mesh.obj");
auto upload = uploadBumpAllocator.allocate(mesh.byteSize); // Custom bump allocator (wraps a gpuMalloc ptr)
mesh.load(upload.cpu);

// Allocate GPU-only memory and copy into it
void* meshGpu = gpuMalloc(mesh.byteSize, MEMORY_GPU);
gpuMemCpy(commandBuffer, meshGpu, upload.gpu);

Vulkan recently got a new extension called VK_EXT_host_image_copy. The driver implements a direct CPU to GPU image copy operation, performing the hardware specific texture swizzle on CPU. This extension is currently only available on UMA architectures, but there’s no technical reason why it’s not available on PCIe ReBAR as well. Unfortunately this API doesn’t support DCC. It would be too expensive to perform DCC compression on the CPU. The extension is mainly useful for block compressed textures, as they don’t require DCC. It can’t universally replace hardware copy to GPU private memory.

There’s also a need for a third memory type, CPU-cached, for readback purposes. This memory type is slower for the GPU to write due to cache coherency with the CPU. Games only use readback seldomly. Common use cases are screenshots and virtual texturing readback. GPGPU algorithms such as AI training and inference lean on efficient communication between the CPU and the GPU.

When we mix the simplicity of CUDA malloc with CPU-mapped GPU memory we get a flexible and fast GPU memory allocation system with minimal API surface. This is an excellent starting point for a minimalistic modern graphics API.

Modern data

CUDA, Metal and OpenCL leverage C/C++ shader languages featuring 64-bit pointer semantics. These languages support loading and storing of structs from/to any appropriately aligned GPU memory location. The compiler handles behind-the-scenes optimizations, including wide loads (combine), register mappings, and bit extractions. Many modern GPUs offer free instruction modifiers for extracting 8/16-bit portions of a register, allowing the compiler to pack 8-bit and 16-bit values into a single register. This keeps the shader code clean and efficient.

If you load a struct of eight 32-bit values, the compiler will most likely emit two 128-bit wide loads (each filling 4 registers), a 4x reduction in load instruction count. Wide loads are significantly faster, especially if the struct contains narrow 8 and 16-bit fields. GPUs are ALU dense and have big register files, but compared to CPUs their memory paths are relatively slow. A CPU often has two load ports each doing a load per cycle. On a modern GPU we can achieve one SIMD load per 4 cycles. Wide load + unpack in the shader is often the most efficient way to handle data.

Compact 8-16 bit data has been traditionally stored in texel buffers (Buffer<T>) in DirectX games. Modern GPUs are optimized for compute workloads. Raw buffer load instructions nowadays have up to 2x higher throughput and up to 3x lower latency than texel buffers. Texel buffers are no longer the optimal choice on modern GPUs. Texel buffers do not support structured data, the user is forced to split their data into SoA layout in multiple texel buffers. Each texel buffer has its own descriptor, which must be loaded before the data can be accessed. This consumes resources (SGPRs, descriptor cache slots) and adds startup latency compared to using a single 64-bit raw pointer. SoA data layout also results in significantly more cache misses for non-linear index lookups (examples: material, texture, triangle, instance, bone id). Texel buffers offer free conversion of normalized ([0,1] and [-1,1]) types to floating point registers. It’s true that there’s no ALU cost, but you lose wide load support (combine loads) and the instruction goes through the slow texture sampler hardware path. Narrow texel buffer loads also add register bloat. RGBA8_UNORM load to vec4 allocates four vector registers immediately. The sampler hardware will eventually write the value to these registers. Compilers try to maximize the distance of load→use by moving load instructions in the beginning of the shader. This hides the load latency by ALU and allows overlapping multiple loads. If we instead use wide raw loads, our uint8x4 data consumes just a single 32-bit register. We unpack the 8-bit channels on use. The register life time is much shorter. Modern GPUs can directly access 16-bit low/high halves of registers without unpack, and some can even do 8-bit (AMD SDWA modifier). Packed double rate math makes 2x16 bit conversion instructions faster. Some GPU architectures (Nvidia, AMD) can also do 64-bit pointer raw loads directly from VRAM into groupshared memory, further reducing the register bloat needed for latency hiding. By using 64-bit pointers, game engines benefit from AI hardware optimizations.

Pointer based systems make memory alignment explicit. When you are allocating a buffer object in DirectX or Vulkan, you need to query the API for alignment. Buffer bind offsets must also be properly aligned. Vulkan has an API for querying the bind offset alignment and DirectX has fixed alignment rules. Alignment contract allows the low level shader compiler to emit optimal code (such as aligned 4x32-byte wide loads). The DirectX ByteAddressBuffer abstraction has a design flaw: load2, load3 and load4 instructions only require 4-byte alignment. The new SM 6.2 load<T> also only requires elementwise alignment (half4 = 2, float4 = 4). Some GPU vendors (like Nvidia) have to split ByteAddressBuffer.load4 into four individual load instructions. The buffer abstraction can’t always shield the user from bad codegen. It makes bad codegen hard to fix. C/C++ based languages (CUDA, Metal) allow the user to explicitly declare struct alignment with the alignas attribute. We use alignas(16) in all our example code root structs.

By default, GPU writes are only visible to the threads inside the same thread group (= inside a compute unit). This allows non-coherent L1$ design. Visibility is commonly provided by barriers. If the user needs memory visibility between the groups in a single dispatch, they decorate the buffer binding with the [globallycoherent] attribute. The shader compiler emits coherent load/store instructions for accesses of that buffer. Since we use 64-bit pointers instead of buffer objects, we offer explicit coherent load/store instructions. The syntax is similar to atomic load/store. Similarly we can provide non-temporal load/store instructions that bypass the whole cache hierarchy.

Vulkan supports 64-bit pointers using the (2019) VK_KHR_buffer_device_address extension ( https://docs.vulkan.org/samples/latest/samples/extensions/buffer_device_address/README.html ). Buffer device address extension is widely supported by all GPU vendors (including mobile), but is not a part of core Vulkan 1.4. The main issue with BDA is lack of pointer support in the GLSL and the HLSL shader languages. The user has to use raw 64-bit integers instead. A 64-bit integer can be cast to a struct. Structs are defined with custom BDA syntax. Array indexing requires declaring an extra BDA struct type with an array in it, if the user wants the compiler to generate the index addressing math. Debugging support is currently limited. Usability matters a lot and BDA will remain a niche until HLSL and GLSL support pointers natively. This is a stark contrast to CUDA, OpenCL and Metal, where native pointer support is a language core pillar and debugging works flawlessly.

DirectX 12 has no support for pointers in shaders. As a consequence, HLSL doesn’t allow passing arrays as function parameters. Simple things like having a material array inside UBO/SSBO requires hacking around with macros. It’s impossible to make reusable functions for reductions (prefix sum, sort, etc), since groupshared memory arrays can’t be passed between functions. You could of course declare a separate global array for each utility header/library, but the compiler will allocate groupshared memory for each of them separately, reducing occupancy. There’s no easy way to alias groupshared memory. GLSL has identical issues. Pointer based languages like CUDA and Metal MSL don’t have such issues with arrays. CUDA has a vast ecosystem of 3rd party libraries, and this ecosystem makes Nvidia the most valued company on the planet. Graphics shading languages need to evolve to meet modern standards. We need a library ecosystem too.

I will be using a C/C++ style shading language similar to CUDA and Metal MSL in my examples, with some HLSL-style system value (SV) semantics mixed in for the graphics specific bits and pieces.

Root arguments

Operating system threading APIs commonly provide a single 64-bit void pointer to the thread function. The operating system doesn’t care about the user’s data input layout. Let’s apply the same ideology to the GPU kernel data inputs. The shader kernel receives a single 64-bit pointer, which we cast to our desired struct (by the kernel function signature). Developers can use the same shared C/C++ header in both CPU and GPU side.

// Common header...
struct alignas(16) Data
{
    // Uniform data
    float16x4 color; // 16-bit float vector
    uint16x2 offset; // 16-bit integer vector
    const uint8* lut; // pointer to 8-bit data array

    // Pointers to in/out data arrays
    const uint32* input;
    uint32* output;
};

// CPU code...
gpuSetPipeline(commandBuffer, computePipeline);

auto data = myBumpAllocator.allocate<Data>(); // Custom bump allocator (wraps gpuMalloc ptr, see appendix)
data.cpu->color = {1.0f, 0.0f, 0.0f, 1.0f};
data.cpu->offset = {16, 0};
data.cpu->lut = luts.gpu + 64; // GPU pointers support pointer math (no need for offset API)
data.cpu->input = input.gpu;
data.cpu->output = output.gpu;

gpuDispatch(commandBuffer, data.gpu, uvec3(128, 1, 1));

// GPU kernel...
[groupsize = (64, 1, 1)]
void main(uint32x3 threadId : SV_ThreadID, const Data* data)
{
    uint32 value = data->input[threadId.x]; 
    // TODO: Code using color, offset, lut, etc...
    data->output[threadId.x] = value;
}

In the example code we use a simple linear bump allocator (myBumpAllocator) for allocating GPU arguments (see appendix for implementation). It returns a struct {void* cpu, void *gpu}. The CPU pointer is used for writing directly to persistently mapped GPU memory and the GPU pointer can be stored to GPU data structures or passed as dispatch command argument.

Most GPUs preload root uniforms (including 64-bit pointers) into constant or scalar registers just before launching a wave. This optimization remains viable: the draw/dispatch command carries the base data pointer. All the input uniforms (including pointers to other data) are found at small fixed offsets from the base pointer. Since shaders are pre-compiled and further optimized into device-specific microcode during the PSO creation, drivers have ample opportunity to set up register preloading and similar root data optimizations. Users should put the most important data in the beginning of the root struct as root data size is limited in some architectures. Our root struct has no hard size limit. The shader compiler will emit standard (scalar/uniform) memory loads for the remaining fields. The root data pointer provided to the shader is const. Shader can’t modify the root input data, as it might be still used by the command processor for preloading data to new waves. Output is done through non-const pointers (see Data::output in above example). By forcing the root data to be const, we also allow GPU drivers to perform their special uniform data path optimizations.

Do we need a special uniform buffer type? Modern shader compilers perform automatic uniformity analysis. If all inputs to an instruction are uniform, the output is also uniform. Uniformity propagates over the shader. All modern architectures have scalar registers/loads or a similar construct (SIMD1 on Intel). Uniformity analysis is used to convert vector loads into scalar loads, which saves registers and reduces latency. Uniformity analysis doesn’t care about the buffer type (UBO vs SSBO). The resource must be readonly (this is why you should always decorate SSBO with readonly attribute in GLSL or prefer SRV over UAV in DirectX 12). The compiler also needs to be able to prove that the pointer is not aliased. The C/C++ const keyword means that data can’t be modified though this pointer, it doesn’t guarantee that other read-write pointers might alias the same memory region. C99 added the restrict keyword for this purpose and CUDA kernels use it frequently. Root pointers in Metal are no-alias (restrict) by default, and so are buffer objects in Vulkan and DirectX 12. We should adopt the same convention to give the compiler more freedom to do optimizations.

The shader compiler is not always able to prove address uniformity at compile time. Modern GPUs opportunistically optimize dynamic uniform address loads. If the memory controller detects that all lanes of a vector load instruction have a uniform address, it emits a single lane load instead of a SIMD wide gather. The result is replicated to all lanes. This optimization is transparent, and doesn’t affect shader code generation or register allocation. Dynamically uniform data is a much smaller performance hit than it used to be in the past, especially when combined with the new fast raw load paths.

Some GPU vendors (ARM Mali and Qualcomm Adreno) take the uniformity analysis a step further. The shader compiler extracts uniform loads and uniform math. A scalar preamble runs before the shader. Uniform memory loads and math is executed once for the whole draw/dispatch and the results are stored in special hardware constant registers (the same registers used by root constants).

All of the above optimizations together provide a better way of handling uniform data than the classic 16KB/64KB uniform/constant buffer abstraction. Many GPUs still have special uniform registers for root constants, system values and the preamble (see above paragraph).

Texture bindings

Ideally, texture descriptors would behave like any other data in GPU memory, allowing them to be freely mixed in structs with other data. However, this level of flexibility isn't universally supported by all modern GPUs. Fortunately bindless texture sampler designs have converged over the last decade, with only two primary methods remaining: 256-bit raw descriptors and the indexed descriptor heap.

AMDs raw descriptor method loads 256-bit descriptors directly from GPU memory into the compute unit’s scalar registers. Eight subsequent 32-bit scalar registers contain a single descriptor. During the SIMD texture sample instruction, the shader core sends a 256-bit texture descriptor and per-lane UVs to the sampler unit. This provides the sampler all the data it needs to address and load texels without any indirections. The drawback is that the 256-bit descriptor takes a lot of register space and needs to be resent to the sampler for each sample instruction.

The indexed descriptor heap approach uses 32-bit indices (20 bits for old Intel iGPUs). 32-bit indices are trivial to store in structs, load into standard SIMD registers and efficient to pass around. During a SIMD sample instruction, the shader core sends the texture index and the per-lane UVs to the sampler unit. The sampler fetches the descriptor from the descriptor heap: heap base address + texture index * stride (256-bits in modern GPUs). The texture heap base address is either abstracted by the driver (Vulkan and Metal) or provided by the user (SetDescriptorHeaps in DirectX 12). Changing the texture heap base address may result in an internal pipeline barrier (on older hardware). On modern GPUs the texture heap 64-bit base address is often part of each sample instruction data, allowing sampling from multiple heaps seamlessly (64-bit base + 32-bit offset per lane). The sampler unit has a tiny internal descriptor cache to avoid indirect reads after the first access. Descriptor caches must be invalidated whenever the descriptor heap is modified.

A few years ago it looked like AMDs scalar register based texture descriptors were the winning formula in the long run. Scalar registers are more flexible than a descriptor heap, allowing descriptors to be embedded inside GPU data structures directly. But there’s a downside. Modern GPU workloads such as ray-tracing and deferred texturing (Nanite) lean on non-uniform texture indices. The texture heap index is not uniform over a SIMD wave. A 32-bit heap index is just 4 bytes, we can send it per lane. In contrast, a 256-bit descriptor is 32 bytes. It is not feasible to fetch and send a full 256-bit descriptor per lane. Modern Nvidia, Apple and Qualcomm GPUs support per-lane descriptor index mode in their sample instructions, making the non-uniform case more efficient. The sampler unit performs an internal loop if required. Inputs/outputs to/from sampler units are sent once, regardless of the heap index coherence. AMDs scalar register based descriptor architecture requires the shader compiler to generate a scalarization loop around the texture sample instruction. This costs extra ALU cycles and requires sending and receiving (partially masked) sampler data multiple times. It’s one of the reasons why Nvidia is faster in ray-tracing than AMD. ARM and Intel use 32-bit heap indices too (like Nvidia, Qualcomm and Apple), but their latest architectures don’t yet have a per-lane heap index mode. They emit a similar scalarization loop as AMD for the non-uniform index case.

All of these differences can be wrapped under an unified texture descriptor heap abstraction. The de-facto texture descriptor size is 256 bits (192 bits on Apple for a separate texture descriptor, sampler is the remaining 32 bits). The texture heap can be presented as a homogeneous array of 256-bit descriptor blobs. Indexing is trivial. DirectX 12 shader model 6.6 provides a texture heap abstraction like this, but doesn’t allow direct CPU or compute shader write access to the descriptor heap memory. A set of APIs are used for creating descriptors and copying descriptors from the CPU to the GPU. The GPU is not allowed to write the descriptors. Today, we can remove this API abstraction completely by allowing direct CPU and GPU write to the descriptor heap. All we need is a simple (user-land) driver helper function for creating a 256-bit (uint64[4]) hardware specific descriptor blob. Modern GPUs have UMA or PCIe ReBAR. The CPU can directly write descriptor blobs into GPU memory. Users can also use compute shaders to copy or generate descriptors. The shader language has a descriptor creation intrinsic too. It returns a hardware specific uint64x4 descriptor blob (analogous to the CPU API). This approach cuts the API complexity drastically and is both faster and more flexible than the DirectX 12 descriptor update model. Vulkan’s VK_EXT_descriptor_buffer ( https://www.khronos.org/blog/vk-ext-descriptor-buffer ) extension (2022) is similar to my proposal, allowing direct CPU and GPU write. It is supported by most vendors, but unfortunately is not part of the Vulkan 1.4 core spec.

// App startup: Allocate a texture descriptor heap (for example 65536 descriptors)
GpuTextureDescriptor *textureHeap = gpuMalloc<GpuTextureDescriptor>(65536);

// Load an image using a 3rd party library
auto pngImage = pngLoad("cat.png");
auto uploadMemory = uploadBumpAllocator.allocate(pngImage.byteSize); // Custom bump allocator (wraps gpuMalloc ptr)
pngImage.load(uploadMemory.cpu);

// Allocate GPU memory for our texture (optimal layout with metadata)
GpuTextureDesc textureDesc { .dimensions = pngImage.dimensions, .format = FORMAT_RGBA8_UNORM, .usage = SAMPLED };
GpuTextureSizeAlign textureSizeAlign = gpuTextureSizeAlign(textureDesc);
void *texturePtr = gpuMalloc(textureSizeAlign.size, textureSizeAlign.align, MEMORY_GPU);
GpuTexture texture = gpuCreateTexture(textureDesc, texturePtr);

// Create a 256-bit texture view descriptor and store it
textureHeap[0] = gpuTextureViewDescriptor(texture, { .format = FORMAT_RGBA8_UNORM });

// Batched upload: begin
GpuCommandBuffer uploadCommandBuffer = gpuStartCommandRecording(queue);

// Copy all textures here!
gpuCopyToTexture(uploadCommandBuffer, texturePtr, uploadMemory.gpu, texture);
// TODO other textures...

// Batched upload: end
gpuBarrier(uploadCommandBuffer, STAGE_TRANSFER, STAGE_ALL, HAZARD_DESCRIPTORS);
gpuSubmit(queue, { uploadCommandBuffer });

// Later during rendering...
gpuSetActiveTextureHeapPtr(commandBuffer, gpuHostToDevicePointer(textureHeap));

It is almost possible to get rid of the CPU side texture object (GpuTexture) completely. Unfortunately the triangle rasterizer units of all modern GPUs are not yet bindless. The CPU driver needs to prepare command packets to bind render targets, depth-stencil buffers, clear and resolve. These APIs don’t use the 256-bit GPU texture descriptor. We need driver specific extra CPU data (stored in the GpuTexture object).

The simplest way to reference a texture in a shader is to use a 32-bit index. A single index can also represent the starting offset of a range of descriptors. This offers a straightforward way to implement the DirectX 12 descriptor table abstraction and the Vulkan descriptor set abstraction without an API. We also get an elegant solution to the fast material switch use case: All we need is a single 64-bit GPU pointer, pointing to a material data struct (containing material properties + 32-bit texture heap start index). Vulkan vkCmdBindDescriptorSets and DirectX 12 SetGraphicsRootDescriptorTable are relatively fast API calls, but they are nowhere as fast as writing a single 64-bit pointer to persistently mapped GPU memory. A lot of complexity is removed by not needing to create, update and delete resource binding API objects. CPU time is also saved as the user no longer needs to maintain a hash map of descriptor sets, a common approach to solve the immediate vs retained mode discrepancy in game engines.

// Common header...
struct alignas(16) Data
{
    uint32 srcTextureBase;
    uint32 dstTexture;
    float32x2 invDimensions;
};

// GPU kernel...
const Texture textureHeap[];

[groupsize = (8, 8, 1)]
void main(uint32x3 threadId : SV_ThreadID, const Data* data)
{
    Texture textureColor = textureHeap[data->srcTextureBase + 0];
    Texture textureNormal = textureHeap[data->srcTextureBase + 1];
    Texture texturePBR = textureHeap[data->srcTextureBase + 2];

    Sampler sampler = {.minFilter = LINEAR, .magFilter = LINEAR}; // Embedded sampler (Metal-style)

    float32x2 uv = float32x2(threadId.xy) * data->invDimensions;

    float32x4 color = sample(textureColor, sampler, uv);
    float32x4 normal = sample(textureNormal, sampler, uv);
    float32x4 pbr = sample(texturePBR, sampler, uv);

    float32x4 lit = calculateLighting(color, normal, pbr);

    TextureRW dstTexture = TextureRW(textureHeap[data->dstTexture]);
    dstTexture[threadId.xy] = lit;
}

Metal 4 manages the texture descriptor heap automatically. Texture objects have .gpuResourceID, which is a 64-bit heap index (Xcode GPU debugger reveals small values such as 0x3). You can directly write texture IDs into GPU structs, as you would use texture indices in DirectX SM 6.6 and Vulkan (descriptor buffer extension). As the heap management in Metal is automatic, users can’t allocate texture descriptors in contiguous ranges. It’s a common practice to store a 32-bit index to the first texture in the range and calculate the indices for other textures in the set (see above code example). Metal doesn’t support this. The user has to write a 64-bit texture handle for each texture separately. To address a set of 5 textures, you need 40 bytes in Metal (5 * 64-bit). Vulkan and DirectX 12 only need 4 bytes (1 * 32-bit). Apple GPU hardware is able to implement SM 6.6 texture heaps. The limitation is the Metal API (software).

Texel buffers can be still supported for backwards compatibility. DirectX 12 stores texel buffer descriptors in the same heap with texture descriptors. A texel buffer functions similarly to a 1d texture (unfiltered tfetch path). Since texel buffers would be mainly used for backwards compatibility, driver vendors wouldn’t need to jump over the hoops to replace them with faster code paths such as raw memory loads behind the scenes. I am not a big fan of driver background threads and shader replacements.

Non-uniform texture index needs to use NonUniformResourceIndex notation similar to GLSL and HLSL. This tells the low level GPU shader compiler to emit a special texture instruction with per-lane heap index, or a scalarization loop for GPUs that only support uniform descriptors. Since buffers are not descriptors, we never need NonUniformResourceIndex for buffers. We simply pass a 64-bit pointer per lane. It works on all modern GPUs. No scalarization loop, no mess. Additionally, the language should natively support ptr[index] notation for memory loads, where the index is 32-bits. Some GPUs support raw memory load instructions with 32-bit per lane offset. It reduces the register pressure. Feedback to GPU vendors: Please add the missing 64-bit shared base + 32-bit per lane offset raw load instruction and 16-bit uv(w) texture load instructions, if your architecture is still missing them.

const Texture textureHeap[];

[groupsize = (8, 8, 1)]
void main(uint32x3 threadId : SV_ThreadID, const Data* data)
{
    // Non-uniform "buffer data" is not an issue with pointer semantics! 
    Material* material = data->materialMap[threadId.xy];

    // Non-uniform texture heap index
    uint32 textureBase = NonUniformResourceIndex(material.textureBase);

    Texture textureColor = textureHeap[textureBase + 0];
    Texture textureNormal = textureHeap[textureBase + 1];
    Texture texturePBR = textureHeap[textureBase + 2];

    Sampler sampler = {.minFilter = LINEAR, .magFilter = LINEAR};

    float32x2 uv = float32x2(threadId.xy) * data->invDimensions;

    float32x4 color = sample(textureColor, sampler, uv);
    float32x4 normal = sample(textureNormal, sampler, uv);
    float32x4 pbr = sample(texturePBR, sampler, uv);
    
    color *= material.color;
    pbr *= material.pbr;

    // Rest of the shader
}

Modern bindless texturing lets us remove all texture binding APIs. A global indexable texture heap makes all textures visible to all shaders. Texture data still needs to be loaded into GPU memory by copy commands (to enable DCC and Morton swizzle). Texture descriptor creation still needs a thin GPU specific user land API. The texture heap can be exposed directly to both the CPU and the GPU as a raw GPU memory array, removing most of the texture heap API complexity compared to DirectX 12 SM 6.6.

Shader pipelines

Since our shader root data is just a single 64-bit pointer and our textures are just 32-bit indices, the shader pipeline creation becomes dead simple. There’s no need to define texture bindings, buffer bindings, bind groups (descriptor sets, argument buffers) or the root signature.

auto shaderIR = loadFile("computeShader.ir");
GpuPipeline computePipeline = gpuCreateComputePipeline(shaderIR);

DirectX 12 and Vulkan utilize complex APIs to bind and set up root signatures, push descriptors, push constants, and descriptor sets. A modern GPU driver essentially constructs a single struct into GPU memory and passes its pointer to the command processor. We have shown that such API complexity is unnecessary. The user simply writes the root struct into persistently mapped GPU memory and passes a 64-bit GPU pointer directly to the draw/dispatch function. Users can also include 64-bit pointers and 32-bit texture heap indices inside their structs to build any indirect data layout that fits their needs. Root bindings APIs and the whole DX12 buffer zoo can be replaced efficiently with 64-bit pointers.​​ This simplifies the shader pipeline creation drastically. We don’t need to define the data layout at all. We successfully removed a massive chunk of API complexity while providing more flexibility to the user.

Static constants

Vulkan, Metal and WebGPU have a concept of static (specialization) constants, locked in at shader pipeline creation. The driver's internal shader compiler applies these constants as literals in the input shader IR and does constant propagation and dead code elimination pass afterward. This can be used to create multiple permutations of the same shader at pipeline creation, reducing the time and storage required for offline compiling all the shader permutations.

Vulkan and Metal have a set of APIs and a special shader syntax for describing the shader specialization constants and their values. It would be nicer to simply provide a C struct that matches the constant struct defined in the shader side. That would require minimal API surface and would bring important improvements.

Vulkan’s specialization constants have a design flaw. Specialization constants can’t modify the descriptor set layouts. Data inputs and outputs are fixed. The user could hack around the limitation by implementing an uber-layout containing all potential inputs/outputs and skip updating unused descriptors, but this is cumbersome and sub-optimal. Our proposed design doesn’t have the same problem. One can simply branch by a constant (the other side is dead code eliminated) and reinterpret the shader data input pointer as a different struct. One could also mimic the C++ inheritance data layout. Use a common layout for the beginning of the input struct and put specialized data at the end. Static polymorphism can be achieved cleanly. Runtime performance is identical to hand optimized shader. The specialization struct can also include GPU pointers, allowing the user to hardcode runtime memory locations, avoiding indirections. This has never been possible in a shader language before. Instead, the GPU vendors had to use background threads to analyze the shaders to do similar shader replacement optimizations at runtime, increasing the CPU cost and the driver complexity significantly.

// Common header...
struct alignas(16) Constants
{
    int32 qualityLevel;
    uint8* blueNoiseLUT;
};

// CPU code...
Constants constants { .qualityLevel = 2, blueNoiseLUT = blueNoiseLUT.gpu };

auto shaderIR = loadFile("computeShader.ir");
GpuPipeline computePipeline = gpuCreateComputePipeline(shaderIR, &constants);

// GPU kernel...
[groupsize = (8, 8, 1)]
void main(uint32x3 threadId : SV_ThreadID, const Data* data, const Constants constants)
{
    if (constants.qualityLevel == 3)
    {
        // Dead code eliminated
    }
}

The shader permutation hell is one of the biggest issues in modern graphics today. Gamers are complaining about stutter, devs are complaining about offline shader compilation taking hours. This new design gives the user added flexibility. They can toggle between static and dynamic behavior inside the shader, making it easy to have a generic fallback and specialization on demand. This design reduces the number of shader permutations and the runtime stalls caused by pipeline creation.

Barriers and fences

The most hated feature in modern graphics APIs must be the barriers. Barriers serve two purposes: enforce producer-to-consumer execution dependencies and transition textures between layouts.

Many graphics programmers have an incorrect mental model about the GPU synchronization. A common belief is that GPU synchronization is based on fine-grained texture and buffer dependencies. In reality, modern GPU hardware doesn’t really care about individual resources. We spend lots of CPU cycles in userland preparing a list of individual resources and how their layouts change, but modern GPU drivers practically throw that list away. The abstraction doesn’t match reality.

Modern bindless architecture gives the GPU a lot of freedom. A shader can write to any 64-bit pointer or any texture in the global descriptor heap. The CPU doesn't know what decisions the GPU is going to make. How is it supposed to emit transition barriers for each affected resource? This is a clear mismatch between bindless architecture and classic CPU-driven rendering APIs today. Let’s investigate why the APIs were designed like this 10 years ago.

AMD GCN had a big influence on modern graphics API design. GCN was ahead of its time with async compute and bindless texturing (using scalar registers to store descriptors), but it also had crucial limitations in its delta color compression (DCC) and cache design. These limitations are a great example why the barrier model we have today is so complex. GCN didn’t have a coherent last-level cache. ROPs (raster operations = pixel shader outputs) had special non-coherent caches directly connected to the VRAM. The driver had to first flush the ROP caches to memory and then invalidate the L2$ to make pixel shader writes visible to shaders and samplers. The command processor also wasn’t a client of the L2$. Indirect arguments written in compute shaders weren’t visible to the command processor without invalidating the whole L2$ and flushing all dirty lines into VRAM. GCN 3 introduced delta color compression (DCC) for ROPs, but AMD’s texture samplers were not able to directly read DCC compressed textures or compressed depth buffers. The driver had to perform an internal decompress compute shader to eliminate the compression. The display engine could not read DCC compressed textures either. The common case of sampling a render target required two internal barriers and flushing all caches (wait for ROPs, flush ROP cache and L2$, run decompress compute shader, wait for compute).

AMD’s new RDNA architecture has several crucial improvements: It has a coherent L2$ covering all memory operations. ROPs and the command processor are clients of the L2$. The only non-coherent caches are the tiny L0$ and K$ (scalar cache) inside the compute units. A barrier now requires only flushing the outstanding writes in the tiny caches into the higher level cache. The driver no longer has to flush the last-level (L2) cache into the VRAM, making barriers significantly faster. RDNA’s improved display engine is capable of reading DCC compressed textures and a (de)compressor sits between the L2$ and the L0$ texture cache. There’s no need to decompress textures into VRAM before sampling, removing the need for texture layout transitions (compressed / uncompressed). All desktop and mobile GPU vendors have reached similar conclusions: Bandwidth is the bottleneck today. We should never waste bandwidth decoding resources into VRAM. Layout transitions are no longer needed.

AMD RDNA (2019): Improved cache hierarchy, DCC and display engine in the RDNA architecture. L2$ contains DCC compressed data. (De)compressor sits between L2$ and lower levels. L0$ (texture) is decompressed. Image © AMD.

Resource lists are the most annoying aspect of barriers in DirectX 12 and Vulkan. Users are expected to track the state of each resource individually, and tell the graphics API their previous and next state for each barrier. This was necessary on 10 year old GPUs as vendors hid various decompress commands under the barrier API. The barrier command functioned as the decompress command, so it had to know which resources required decompression. Today’s hardware doesn’t need texture layouts or decompress steps. Vulkan just got a new VK_KHR_unified_image_layouts ( https://www.khronos.org/blog/so-long-image-layouts-simplifying-vulkan-synchronisation ) extension (2025), removing the image layout transitions from the barrier command. But it still requires the user to list individual textures and buffers. Why is this?

The main reason is legacy API and tooling compatibility. People are used to thinking about resource dependencies and the existing Vulkan and DirectX 12 validation layers are designed that way. However, the barrier command executed by the GPU contains no information about textures or buffers at all. The resource list is consumed solely by the driver.

Our modern driver loops through your resource list and populates a set of flags. Drivers no longer need to worry about resource layouts or last level cache coherency, but there still exists tiny non-coherent caches that need flushing in special cases. Modern GPUs flush the majority of the non-coherent caches automatically in every barrier. For example the AMD L0$ and K$ (scalar cache) are always flushed, since every pass writes some outputs and these outputs live in some of these caches. Fine grained tracking of all write addresses would be too expensive. Tiny non-coherent caches tend to be inclusive. Modified lines get flushed to the next cache level. This is fast and doesn’t produce VRAM traffic. Some architectures have special caches that are not automatically flushed. Examples: descriptor caches in the texture samplers (see above chapter), rasterizer ROP caches and HiZ caches. The command processor commonly runs ahead to reduce the wave spawn latency. If we write indirect arguments in a shader, we need to inform the GPU to stall the command processor prefetcher to avoid a race. The GPU doesn’t actually know whether your compute shader was writing into an indirect argument buffer or not. In DirectX 12 the buffer is transitioned to D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT and in Vulkan the consumer dependency has a special stage VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT. When a barrier has a resource transition like this or a stage dependency like this, the driver will include command processor prefetcher stall flag into the barrier.

A modern barrier design replaces the resource list with a single bitfield describing what happens to these special non-coherent caches. Special cases include: Invalidate texture descriptors, invalidate draw arguments and invalidate depth caches. These flags are needed when we generate draw arguments, write to the descriptor heap or write to a depth buffer with a compute shader. Most barriers don’t need special cache invalidation flags.

Some GPUs still need to decompress data in special cases. For example during a copy or a clear command (fast clear eliminate if clear color has changed). Copy and clear commands take the affected resource as a parameter. The driver can take necessary steps to decode the data if needed. We don’t need a resource list in our barrier for these special cases. Not all formats and usage flags support compression. The driver will keep the data uncompressed in these cases, instead of transitioning it back and forth, wasting bandwidth.

A standard UAV barrier (compute → compute) is trivial.

gpuBarrier(commandBuffer, STAGE_COMPUTE, STAGE_COMPUTE);

If you write to the texture descriptor heap (uncommon), you need to add a special flag.

gpuBarrier(commandBuffer, STAGE_COMPUTE, STAGE_COMPUTE, HAZARD_DESCRIPTORS);

A barrier between rasterizer output and pixel shader is a common case for offscreen render target → sampling. Our example has dependency stages set up in a way that the barrier doesn’t block vertex shaders, allowing vertex shading (and tile binning on mobile GPUs) to overlap with previous passes. A barrier with raster output stage (or later) as the producer automatically flushes non-coherent ROP caches if the GPU architecture needs that. We don’t need an explicit flag for it.

gpuBarrier(commandBuffer, STAGE_RASTER_COLOR_OUT | STAGE_RASTER_DEPTH_OUT, STAGE_PIXEL_SHADER);

Users only describe the queue execution dependencies: producer and consumer stage masks. There’s no need to track the individual texture and buffer resource states, removing a lot of complexity and saving a significant amount of CPU time versus the current DirectX 12 and Vulkan designs. Metal 2 has a modern barrier design already: it doesn’t use resource lists.

Many GPUs have custom scratchpads memories: Groupshared memory inside each compute unit, tile memory, large shared scratchpads like the Qualcomm GMEM. These memories are managed automatically by the driver. Temporary scratchpads like groupshared memory are never stored to memory. Tile memories are stored automatically by the tile rasterizer (store op == store). Uniform registers are read-only and pre-populated before each draw call. Scratchpads and uniform registers don’t have cache coherency protocols and don’t interact with the barriers directly.

Modern GPUs support a synchronization command that writes a value to memory when a shader stage is finished, and a command that waits for a value to appear in memory location before a shader stage is allowed to begin (wait includes optional cache flush semantics). This is equivalent to splitting the barrier into two: the producer and the consumer. DirectX 12 split barriers and Vulkan event→wait are examples of this design. Splitting the barrier into consumer→producer allows putting independent work between them, avoiding draining the GPU.

Vulkan event→wait (and DX12 split barriers) see barely any use. The main reason is that normal barriers are already highly complicated, and developers want to avoid extra complexity. Driver support for split barriers also hasn’t been perfect in the past. Removing the resource lists simplifies the split barriers significantly. We can also make split barriers semantically similar to timeline semaphores: Signal command writes to a monotonically increasing 64-bit value (atomic max) and wait command waits for the value to be >= N (greater equal). The counter is just a GPU memory pointer, no persistent API object is required. This provides us with a significantly simpler event→wait API.

gpuSignalAfter(commandBuffer, STAGE_RASTER_COLOR_OUT, gpuPtr, counter, SIGNAL_ATOMIC_MAX);
// Put independent work here
gpuWaitBefore(commandBuffer, STAGE_PIXEL_SHADER, gpuPtr, counter++, OP_GREATER_EQUAL);

This API is much simpler than the existing VkEvent API, yet offers improved flexibility. In the above example we implemented the timeline semaphore semantics, but we can implement other patterns too, such as waiting multiple producers using a bitmask: mark bits with SIGNAL_ATOMIC_OR and wait for all bits in a mask to be set (mask is an optional parameter in the gpuWaitBefore command).

Cascading signal→wait with independent work between producer→consumer avoids GPU stalls. Image © Timothy Lottes.

GPU→CPU synchronization was initially messy in Vulkan and Metal. Users needed a separate fence object for each submit. N buffering was a common technique for reusing the objects. This is a similar usability issue as discussed above regarding VkEvent. DirectX 12 was the first API to solve the GPU→CPU synchronization cleanly with timeline semaphores. Vulkan 1.2 and Metal 2 adapted the same design later. A timeline semaphore needs only a single 64-bit monotonically increasing counter. This reduces complexity over the older Vulkan and Metal fence APIs, which many engines still use today.

#define FRAMES_IN_FLIGHT 2

GpuSemaphore frameSemaphore = gpuCreateSemaphore(0);
uint64 nextFrame = 1;

while (running)
{
    if (nextFrame > FRAMES_IN_FLIGHT) 
    {
        gpuWaitSemaphore(frameSemaphore, nextFrame - FRAMES_IN_FLIGHT);
    }
    
    // Render the frame here

    gpuSubmit(queue, {commandBuffer}, frameSemaphore, nextFrame++);
}

gpuDestroySemaphore(frameSemaphore);

Our proposed barrier design is a massive improvement over DirectX 12 and Vulkan. It reduces the API complexity significantly. Users no longer need to track individual resources. Our simple hazard tracking has queue + stage granularity. This matches what GPU hardware does today. Game engine graphics backends can be simplified and CPU cycles are saved.

Command buffers

Vulkan and DirectX 12 were designed to promote the pre-creation and reuse of resources. Early Vulkan examples recorded a single command buffer at startup, replaying it every frame. Developers quickly discovered that command buffer reuse was impractical. Real game environments are dynamic and the camera is in constant motion. The visible object set changes frequently.

Game engines ignored prerecorded command buffers entirely. Metal and WebGPU feature transient command buffers, which are created just before recording and disappear after GPU has finished rendering. This eliminates the need for command buffer management and prevents multiple submissions of the same commands. GPU vendors recommend one shot command buffers (a resettable command pool per frame in flight) in Vulkan too, as it simplifies the driver’s internal memory management (bump allocator vs heap allocator). The best practices match Metal and WebGPU design. Persistent command buffer objects can be removed. That API complexity didn’t provide anything worth using.

while (running)
`
    GpuCommandBuffer commandBuffer = gpuStartCommandRecording(queue);
    // Render frame here
}

Graphics shaders

Let’s start with a burning question: Do we need graphics shaders anymore? UE5 Nanite uses compute shaders to plot pixels using 64-bit atomics. High bits contain the pixel depth and low bits contain the payload. Atomic-min ensures that the closest surface remains. This technique was first presented at SIGGRAPH 2015 by Media Molecule Dreams (Alex Evans). Hardware rasterizer still has some advantages, like hierarchical/early depth-stencil tests. Nanite has to lean solely on coarse cluster culling, which results in extra overdraw with kitbashed content. Ubisoft (me and Ulrich Haar) presented this two-pass cluster culling algorithm at SIGGRAPH 2015. Ubisoft used cluster culling in combination with the hardware rasterizer for more fine grained culling. Today’s GPUs are bindless and much better suited for GPU-driven workloads like this. 10 years ago Ubisoft had to lean on virtual texturing (all textures in the same atlas) instead of bindless texturing. Despite many compute-only rasterizers today (Nanite, SDF sphere tracing, DDA voxel tracing) the hardware rasterizer still remains the most used technique for rendering triangles in games today. It’s definitely worth discussing how to make the rasterization pipeline more flexible and easier to use.

The modern shader framework has grown to 16 shader entry points. We have eight entry points for rasterization (pixel, vertex, geometry, hull, domain, patch constant, mesh and amplification), and six for ray-tracing (ray generation, miss, closest hit, any hit, intersection and callable). In comparison, CUDA has a single entry point: kernel. This makes CUDA composable. CUDA has a healthy ecosystem of 3rd party libraries. New GPU hardware blocks such as the tensor cores (AI) are exposed as intrinsic functions. This is how it all started in the graphics land as well: texture sampling was our first intrinsic function. Today, texture sampling is fully bindless and doesn’t even require driver setup. This is the design developers prefer. Simple, easy to compose, and extend.

We recently got more intrinsics: inline raytracing and cooperative matrix (wave matrix in DirectX 12, subgroup matrix in Metal). I am hoping that this is the new direction. We should start tearing down the massive 16 shader framework and replacing it with intrinsics that can be composed in a flexible way.

Solving the shader framework complexity is a massive topic. To keep the scope of this blog post in check, I will today only discuss compute shaders and raster pipelines. I am going to be writing a followup about simplifying the shader framework, including modern topics such as ray-tracing, shader execution reordering (SER), dynamic register allocation extensions and Apple’s new L1$ backed register file (called dynamic caching).

Raster pipelines

There are two relevant raster pipelines today: Vertex+pixel and mesh+pixel. Mobile GPUs employing tile based deferred rendering (TBDR) perform per-triangle binning. Tile size is commonly between 16x16 to 64x64 pixels, making meshlets too coarse grained primitive for binning. Meshlet has no clear 1:1 lane to vertex mapping, there’s no straightforward way to run a partial mesh shader wave for selected triangles. This is the main reason mobile GPU vendors haven’t been keen to adapt the desktop centric mesh shader API designed by Nvidia and AMD. Vertex shaders are still important for mobile.

I will not be discussing geometry, hull, domain, and patch constant (tessellation) shaders. The graphics community widely considers these shader types as failed experiments. They all have crucial performance issues in their design. In all relevant use cases, you can run a compute prepass generating an index buffer to outperform these stages. Additionally, mesh shaders allow generating a compact 8-bit index buffer into on-chip memory, further increasing the performance gap over these legacy shader stages.

Our goal is to build a modern PSO abstraction with a minimal amount of baked state. One of the main critiques of Vulkan and DirectX 12 has been the pipeline permutation explosion. The less state we have inside the PSO, the less pipeline permutations we get. There are two main areas to improve: graphics shader data bindings and the rasterizer state.

Graphics shader bindings

Vertex+pixel shader pipeline needs several additional inputs compared to a compute kernel: vertex buffers, index buffer, rasterizer state, render target views and a depth-stencil view. Let’s start by discussing the shader visible data bindings.

Vertex buffer bindings are easy to solve: We simply remove them. Modern GPUs have fast raw load paths. Most GPU vendors have been emulating vertex fetch hardware already for several generations. Their low level shader compiler reads the user defined vertex layout and emits appropriate raw load instructions in the beginning of the vertex shader.

The vertex bindings declaration is another example of a special C/C++ API for defining a struct memory layout. It adds complexity and forces compiling multiple PSO permutations for different layouts. We simply replace the vertex buffers with standard C/C++ structs. No API is required.

// Common header...
struct Vertex
{
    float32x4 position;
    uint8x4 normal;
    uint8x4 tangent;
    uint16x2 uv;
};

struct alignas(16) Data
{
    float32x4x4 matrixMVP;
    const Vertex *vertices;
};

// CPU code...
gpuSetPipeline(commandBuffer, graphicsPipeline);

auto data = myBumpAllocator.allocate<Data>();
data.cpu->matrixMVP = camera.viewProjection * modelMatrix;
data.cpu->vertices = mesh.vertices;

gpuDrawIndexed(commandBuffer, data.gpu, mesh.indices, mesh.indexCount);

// Vertex shader...
struct VertexOut 
{
    float32x4 position : SV_Position;
    float16x4 normal;
    float32x2 uv;
};

VertexOut main(uint32 vertexIndex : SV_VertexID, const Data* data)
{
    Vertex vertex = data->vertices[vertexIndex];
    float32x4 position = data->matrixMVP * vertex.position;
    // TODO: Normal transform here
    return { .position = position, .normal = normal, .uv = vertex.uv };
}

The same is true for per-instance data and multiple vertex streams. We can implement them efficiently with raw memory loads. When we use raw load instructions, we can dynamically adjust the vertex stride, branch over secondary vertex buffer loads and calculate our vertex indices using custom formulas to implement clustered GPU-driven rendering, particle quad expansion, higher order surfaces, efficient terrain rendering and many other algorithms. Additional shader entry points and binding APIs are not needed. We can use our new static constant system to dead code eliminate vertex streams at pipeline creation or provide a static vertex stride if we so prefer. All the old optimization strategies still exist, but we can now mix and match techniques freely to match our renderer’s needs.

// Common header...
struct VertexPosition
{
    float32x4 position;
};

struct VertexAttributes
{
    uint8x4 normal;
    uint8x4 tangent;
    uint16x2 uv;
};

struct alignas(16) Instance
{
    float32x4x4 matrixModel;
}

struct alignas(16) Data
{
    float32x4x4 matrixViewProjection;
    const VertexPosition *vertexPositions;
    const VertexAttributes *vertexAttribues;
    const Instance *instances;
};

// CPU code...
gpuSetPipeline(commandBuffer, graphicsPipeline);

auto data = myBumpAllocator.allocate<Data>();
data.cpu->matrixViewProjection = camera.viewProjection;
data.cpu->vertexPositions = mesh.positions;
data.cpu->vertexAttributes = mesh.attributes;
data.cpu->instances = batcher.instancePool + instanceOffset; // pointer arithmetic is convenient

gpuDrawIndexedInstanced(commandBuffer, data.gpu, mesh.indices, mesh.indexCount, instanceCount);

// Vertex shader...
struct VertexOut 
{
    float32x4 position : SV_Position; // SV values are not real struct fields (doesn't affect the layout)
    float16x4 normal;
    float32x2 uv;
};

VertexOut main(uint32 vertexIndex : SV_VertexID, uint32 instanceIndex : SV_InstanceID, const Data* data)
{
    Instance instance = data->instances[SV_InstanceIndex];

    // NOTE: Splitting positions/attributes benefits TBDR GPUs (vertex shader is split in two parts)
    VertexPosition vertexPosition = data->vertexPositions[SV_VertexIndex];
    VertexAttributes vertexAttributes = data->vertexAttributes[SV_VertexIndex];

    float32x4x4 matrix = data->matrixViewProjection * instance.matrixModel;
    float32x4 position = matrix * vertexPosition.position;

    // TODO: Normal transform here

    return { .position = position, .normal = normal, .uv = vertexAttributes.uv };
}

The index buffer binding is still special. GPUs have index deduplication hardware. We don’t want to run the vertex shader twice for the same vertex. The index deduplication hardware packs the vertex waves eliminating duplicate vertices. Index buffering is still a crucial optimization today. Non-indexed geometry executes 3 vertex shader invocations (lanes) per triangle. A perfect grid has two triangles per cell, thus it only needs one vertex shader invocation per two triangles (ignoring the last row/column). Modern offline vertex cache optimizers output meshes with around 0.7 vertices per triangle efficiency. We can achieve around 4x to 6x reduction in vertex shading cost with index buffer in real world scenarios.

The index buffer hardware nowadays connects to the same cache hierarchy as all the other GPU units. Index buffer is simply an extra GPU pointer in the drawIndexed call. That’s the sole API surface we need for index buffering.

Mesh shaders lean on offline vertex deduplication. A common implementation shades one vertex per lane, and outputs it into on-chip memory. An 8-bit local index buffer tells the rasterizer which 3 vertices are used by each triangle. Since all the meshlet outputs are available at once and are already transformed in on-chip storage, there’s no need to deduplicate or pack vertices after triangle setup. This is why mesh shaders don’t need the index deduplication hardware or the post transform cache. All mesh shader inputs are raw data. No extra API surface is needed beyond the gpuDrawMeshlets command.

My example mesh shader uses 128 lane thread groups. Nvidia supports up to 126 vertices and 64 triangles per output meshlet. AMD supports 256 vertices and 128 triangles. The shader masks out excess lanes. Since there’s never more than 64 triangles, you might also opt for a 64 lane thread group for optimal triangle lane utilization and do a two iteration loop for vertex shading. My triangle fetch logic is just a single memory load instruction, wasting half of the lanes there isn’t a problem. I chose the extra parallelism for vertex shading instead. Optimal choices depend on your workload and the target hardware.

// Common header...
struct Vertex
{
    float32x4 position;
    uint8x4 normal;
    uint8x4 tangent;
    uint16x2 uv;
};

struct alignas(16) Meshlet
{
    uint32 vertexOffset;
    uint32 triangleOffset;
    uint32 vertexCount;
    uint32 triangleCount;
};

struct alignas(16) Data
{
    float32x4x4 matrixMVP;
    const Meshlet *meshlets;
    const Vertex *vertices;
    const uint8x4 *triangles;
};

// CPU code...
gpuSetPipeline(commandBuffer, graphicsMeshPipeline);

auto data = myBumpAllocator.allocate<Data>();
data.cpu->matrixMVP = camera.viewProjection * modelMatrix;
data.cpu->meshlets = mesh.meshlets;
data.cpu->vertices = mesh.vertices;
data.cpu->triangles = mesh.triangles;

gpuDrawMeshlets(commandBuffer, data.gpu, uvec3(mesh.meshletCount, 1, 1));

// Mesh shader...
struct VertexOut 
{
    float32x4 position : SV_Position;
    float16x4 normal;
    float32x2 uv;
};

[groupsize = (128, 1, 1)]
void main(uint32x3 groupThreadId : SV_GroupThreadID, uint32x3 groupId : SV_GroupID, const Data* data)
{
    Meshlet meshlet = data->meshlets[groupId.x];

    // Meshlet output allocation intrinsics
    VertexOut* outVertices = allocateMeshVertices<VertexOut>(meshlet.vertexCount);
    uint8x3* outIndices = allocateMeshIndices(meshlet.triangleCount);

    // Triangle indices (3x 8 bit)
    if (groupThreadId.x < meshlet.triangleCount)
    {
        outIndices[groupThreadId.x] = triangles[meshlet.triangleOffset + groupThreadId.x].xyz;
    }

    // Vertices
    if (groupThreadId.x < meshlet.vertexCount)
    {
        Vertex vertex = data->vertices[meshlet.vertexOffset + groupThreadId.x];
        float32x4 position = data->matrixMVP * vertex.position;
        // TODO: Normal transform here
        outVertices[groupThreadId.x] = { .position = position, .normal = normal, .uv = vertex.uv };
    }
}

Both vertex shaders and mesh shaders use pixel shaders. Rasterizer spawns pixel shader work based on triangle pixel coverage, HiZ, and early depth/stencil test results. Hardware can pack multiple triangles and multiple instances in the same pixel shader wave. Pixel shaders itself aren’t that special. Nowadays pixel shaders run on the same SIMD cores as all the other shader types. There are some special inputs available: interpolated vertex outputs, screen location, sample index and coverage mask, triangle id, triangle facing, etc. Special inputs are declared as kernel function parameters using the system value (: SV) semantics, similar to existing APIs.

// Pixel shader...
const Texture textureHeap[];

struct VertexIn // Matching vertex shader output struct layout
{
    float16x4 normal;
    float32x2 uv;
};

struct PixelOut 
{
    float16x4 color : SV_Color0;
};

PixelOut main(const VertexIn &vertex, const DataPixel* data)
{
    Texture texture = textureHeap[data->textureIndex];
    Sampler sampler = {.minFilter = LINEAR, .magFilter = LINEAR};

    float32x4 color = sample(texture, sampler, vertex.uv);
    return { .color = color };
}

The removal of data bindings makes vertex and pixel shaders simpler to use. All of the complex data bindings APIs are replaced by a 64-bit GPU pointer. Users are able to write flexible vertex fetch code to avoid creating a PSO permutation per vertex layout.

Rasterizer state

Legacy APIs (OpenGL and DirectX 9) had fine grained commands for setting all the shader inputs and rasterizer states. The driver had to build shader pipelines on demand. Hardware specific rasterizer, blender, and input assembler command packets were constructed from the shadow state that combined all individual fine grained states. Vulkan 1.0 and DirectX 12 chose the fully opposite design. All state is baked in the PSO ahead of time. Only a select few states, such as viewport rect, scissor rect, and stencil values, can be changed dynamically. This resulted in a massive explosion of PSO permutations.

PSO creation is expensive, as it requires calling the GPU driver’s low-level shader compiler. PSO permutations consume a significant amount of storage and RAM. Changing the PSO is the most expensive state change. The small performance advantages that some vendors achieved by embedding render state directly into the shader microcode were overshadowed by the performance issues caused by significantly amplified pipeline creation, binding and data management costs everywhere. The pendulum swung too far to the opposite side.

Modern GPUs are ALU dense. Nvidia and AMD recently doubled their ALU rate with additional pipelines. Apple also doubled their fp32 pipelines in their M-series chips. Simple states resulting only in a constant replacement in the shader should not require pipeline duplication, even if it adds an extra ALU instruction or wastes an uniform register. Most shaders today are not ALU bound. The cost is often not measurable, but the benefits of having less permutations are significant. Vulkan 1.3 is a big step in the right direction. A lot of baked PSO states can now be set dynamically.

If we investigate deeper, we notice that all GPUs use command packets for configuring their rasterizer and depth-stencil units. These command packets are not directly tied to the shader microcode. We don’t need to modify the shader microcode to change the rasterizer and depth-stencil state. Metal has a separate depth-stencil state object and a separate command for applying it. A separate state object reduces the PSO permutations and reduces the expensive shader binding calls. Vulkan 1.3 dynamic state achieves similar PSO permutation reduction, but is more fine grained. Metal’s design is a better match for the actual hardware command packets. Bigger packets reduce the API bloat and overhead. DirectX 12 unfortunately still bundles most of the depth-stencil state inside the PSO (stencil ref and depth bias are the only dynamic state). In our design the depth-stencil state is a separate object.

GpuDepthStencilDesc depthStencilDesc = 
{
    .depthMode = DEPTH_READ | DEPTH_WRITE,
    .depthTest = OP_LESS_EQUAL,
    .depthBias = 0.0f,
    .depthBiasSlopeFactor = 0.0f,
    .depthBiasClamp = 0.0f,
    .stencilReadMask = 0xff,
    .stencilWriteMask = 0xff,
    .stencilFront =
    {
        .test = OP_ALWAYS,
        .failOp = OP_KEEP,
        .passOp = OP_KEEP,
        .depthFailOp = OP_KEEP,
        .reference = 0
    },
    .stencilBack =
    {
        .test = COMPARE_ALWAYS,
        .failOp = OP_KEEP,
        .passOp = OP_KEEP,
        .depthFailOp = OP_KEEP,
        .reference = 0
    }
};

// A minimal way to descibe the above (using C++ API struct default values):
GpuDepthStencilDesc depthStencilDesc = 
{
    .depthMode = DEPTH_READ | DEPTH_WRITE,
    .depthTest = OP_LESS_EQUAL,
};

GpuDepthStencilState depthStencilState = gpuCreateDepthStencilState(depthStencilDesc);

Immediate mode (desktop) GPUs have similar command packets for configuring the alpha blender unit. If we were designing DirectX 13, we would simply split the blend state object out of the PSO and call it a day. But we are designing a cross platform API, and blending works completely differently on mobile GPUs.

Mobile GPUs (TBDR) have always supported programmable blending. A render tile fits into a scratchpad memory close to the compute unit (such as the groupshared memory), allowing pixel shaders a direct low latency read+write access to previously rasterized pixels. Most mobile GPUs don’t have any fixed function blending hardware. When a traditional graphics API is used, the driver's low level shader compiler adds blending instructions at the end of the shader. This is analogous to the vertex fetch code generation (described above). If we were designing an API solely for mobile GPUs, we would get rid of the blend state APIs completely, just like we got rid of the vertex buffers. Mobile centric APIs expose a framebuffer fetch intrinsic to efficiently obtain current pixel’s previous color. The user can write any blending formula they want, including complex formulas to implement advanced algorithms such as order independent transparency. The user can also write a generic parametrised formula to eliminate the PSO permutation explosion. As we can see, both the desktop and the mobile GPUs have their own ways to reduce the pipeline permutations regarding blending, the limitation is the current APIs.

Vulkan subpasses were designed to wrap framebuffer fetch into a cross platform API. This was another misstep in Vulkan design. Vulkan inherited a simple low level design from Mantle, but Vulkan was designed as an OpenGL replacement, so it had to target all mobile and desktop GPU architectures. Wrapping two entirely different architecture types under the same API isn’t easy. Subpasses ended up being a high level concept inside a low level API. A subpass could define an entire chain of render passes but pretend that it’s just a single render pass. Subpasses increased driver complexity and made the shader and renderpass APIs needlessly complex. Users were forced to create complex persistent multi-render pass objects ahead of time and pass those objects into shader pipeline creation. Shader pipelines became multi-pipelines under the hood (one pipeline per sub-pass). Vulkan added all of this complexity simply to avoid exposing the framebuffer fetch intrinsic to the shader language. To add insult to injury, the subpasses weren’t even good enough to solve the programmable blending. Pixel ordering is only preserved at pass boundaries. Subpasses were only useful for narrow 1:1 multi-pass use cases. Vulkan 1.3 scrapped the subpasses and introduced “dynamic rendering”. Users no longer need to create persistent render pass objects, just like in Metal, DirectX 12 and WebGPU. This is a great example of how a complex framework can be tempting for API designers, but developers prefer simple shader intrinsics. Game engines already support building different shaders to different platforms. Apple’s Metal examples do the same: Framebuffer fetch is used on iOS and a traditional multipass algorithm on Mac.

It’s apparent that we can’t abstract hardware differences regarding blending and framebuffer fetch. Vulkan 1.0 tried that and failed miserably. The correct solution is to provide the user a choice. They can choose to embed the blend state into the PSO. This works on all platforms and is the perfect approach for shaders that don’t suffer from blend state related pipeline permutation issues. Mobile GPU’s internal driver shader compiler adds the blending instructions in the end of the pixel shader as usual. On immediate mode (desktop) GPUs (and some mobile GPUs), the user can choose to use separate blend state objects. This reduces the amount of PSO permutations and makes it faster to change the blend state at runtime, as a full pipeline change is not needed (only a blend state configuration packet is sent).

GpuBlendDesc blendDesc = 
{
    .colorOp = OP_ONE,
    .srcColorFactor = FACTOR_SRC_ALPHA,
    .dstColorFactor = FACTOR_ONE_MINUS_SRC_ALPHA,
    .alphaOp = OP_ONE,
    .srcAlphaFactor = FACTOR_SRC_ALPHA,
    .dstAlphaFactor = FACTOR_ONE_MINUS_SRC_ALPHA,
    .colorWriteMask = 0xf
};

// Create blend state object (needs feature flag)
GpuBlendState blendState = gpuCreateBlendState(blendDesc);

// Set dynamic blend state (needs feature flag)
gpuSetBlendState(commandBuffer, blendState);

On mobile GPUs the user can embed the blend state into the PSO as usual, or choose to use framebuffer fetch to write a custom blending formula. If the mobile developer wants to avoid compiling multiple PSO permutations for different alpha blending modes, they can write a general formula parametrized with dynamic draw struct inputs.

// Standard percentage blend formula (added automatically by internal shader compiler)
dst.rgb = src.rgb * src.a + dst.rgb * (1.0 - src.a);
dst.a = src.a * src.a + dst.a * (1.0 - src.a);

// Custom formula supporting all blend modes used by HypeHype
const BlendParameters& p = data->blendParameters;
vec4 fs = src.a * vec4(p.sc_sa.xxx + p.sc_one.xxx, p.sa_sa + p.sa_one) + dst.rgba * vec4(p.sc_dc.xxx, sa_da);
vec4 fd = (1.0 - src.a) * vec4(p.dc_1msa.xxx, p.da_1msa) + vec4(p.dc_one.xxx, p.da_one);
dst.rgb = src.rgb * fs.rgb + dst.rgb * fd.rgb;
dst.a  = src.a * fs.a + dst.a * fd.a;

As the blend state is separated from the PSO, it’s possible we lose some automatic dead code optimizations. If the user wants to disable the color output, they traditionally use the colorWriteMask in the blend state. Since the blend state is burned in the PSO, the compiler can do dead code elimination based on it. To allow similar dead code optimizations, we have writeMask for each color target in the PSO.

Dual source blending is a special blend mode requiring two color outputs from the pixel shader. Dual source blending only supports a single render target. Since our blend state can be separate, we need to have a supportDualSourceBlending field in our PSO desc. When enabled, the shader compiler knows the second output is for dual source blending. The validation layer would complain if the output is not present. A pixel shader exporting two colors can be used without dual source blending (the second color is ignored), but there’s a small cost for exporting two colors.

The remaining rendering state in the PSO is minimal: primitive topology, render target and depth-stencil target formats, MSAA sample count and alpha to coverage. All of this state affects the generated shader microcode so it needs to stay in the PSO. We never want to rebuild the shader PSO microcode due to a state change. If an embedded blend state is used, it's also burned in the PSO. This leaves us with a simple raster state struct for PSO creation.

GpuRasterDesc rasterDesc = 
{
    .topology = TOPOLOGY_TRIANGLE_LIST,
    .cull = CULL_CCW,
    .alphaToCoverage = false,
    .supportDualSourceBlending = false,
    .sampleCount = 1`
    .depthFormat = FORMAT_D32_FLOAT,
    .stencilFormat = FORMAT_NONE,
    .colorTargets = 
    {
        { .format = FORMAT_RG11B10_FLOAT	},		// G-buffer with 3 render targets
        { .format = FORMAT_RGB10_A2_UNORM },
        { .format = FORMAT_RGBA8_UNORM }
    },
    .blendstate = GpuBlendDesc { ... }			// optional (embedded blend state, otherwise dynamic)
};

// A minimal way to descibe the above (using C++ API struct default values):
GpuRasterDesc rasterDesc = 
{
    .depthFormat = FORMAT_D32_FLOAT,
    .colorTargets = 
    {
        { .format = FORMAT_RG11B10_FLOAT	},
        { .format = FORMAT_RGB10_A2_UNORM },
        { .format = FORMAT_RGBA8_UNORM }
    },
};

// Pixel + vertex shader
auto vertexIR = loadFile("vertexShader.ir");
auto pixelIR = loadFile("pixelShader.ir");
GpuPipeline graphicsPipeline = gpuCreateGraphicsPipeline(vertexIR, pixelIR, rasterDesc);

// Mesh shader
auto meshletIR = loadFile("meshShader.ir");
auto pixelIR = loadFile("pixelShader.ir");
GpuPipeline graphicsMeshletPipeline = gpuCreateGraphicsMeshletPipeline(meshletIR, pixelIR, rasterDesc);

HypeHype’s Vulkan shader PSO initialization backend code is 400 lines, and I would consider it compact compared to other engines I have been developing. Here, we managed to initialize a pixel + vertex shader with just 18 lines of code. It’s easy to read and understand. Yet, there’s no compromise on performance.

Rendering with the raster pipeline is similar to rendering with a compute pipeline. Instead of providing one data pointer, we provide two since there’s two kernel entry points: One for vertex shader and one for pixel shader. Metal has a separate set of data binding slots for vertex and pixel shaders. DirectX, Vulkan and WebGPU use a visibility mask (vertex, pixel, compute, etc) for each individual binding. Many engines choose to bind the same data to both vertex and pixel shader. This is a fine practice on DirectX, Vulkan and WebGPU as you can combine the mask bits, but doubles the binding calls on Metal. Our proposed approach using two data pointers is the best of both worlds. You can simply pass the same pointer twice if you want to use the same data in both the vertex and the pixel shader. Or you can provide independent data pointers, if you prefer full separation between the shader stages. The shader compiler does dead code elimination and constant/scalar preload optimizations separately for pixel and vertex shader. Neither data sharing nor data duplication results in bad performance. The user can choose whatever fits their design.

// Common header...
struct Vertex
{
    float32x4 position;
    uint16x2 uv;
};

struct alignas(16) DataVertex
{
    float32x4x4 matrixMVP;
    const Vertex *vertices;
};

struct alignas(16) DataPixel
{
    float32x4 color;
    uint32 textureIndex;
};

// CPU code...
gpuSetDepthStencilState(commandBuffer, depthStencilState);
gpuSetPipeline(commandBuffer, graphicsPipeline);

auto dataVertex = myBumpAllocator.allocate<DataVertex>();
dataVertex.cpu->matrixMVP = camera.viewProjection * modelMatrix;
dataVertex.cpu->vertices = mesh.vertices;

auto dataPixel = myBumpAllocator.allocate<DataPixel>();
dataPixel.cpu->color = material.color;
dataPixel.cpu->textureIndex = material.textureIndex;

gpuDrawIndexed(commandBuffer, dataVertex.gpu, dataPixel.gpu, mesh.indices, mesh.indexCount);

// Vertex shader...
struct VertexOut 
{
    float32x4 position : SV_Position; // SV values are not real struct fields (doesn't affect the layout)
    float32x2 uv;
};

VertexOut main(uint32 vertexIndex : SV_VertexID, const DataVertex* data)
{
    Vertex vertex = data.vertices[vertexIndex];
    float32x4 position = data->matrixMVP * vertex.position;
    return { .position = position, .uv = vertex.uv };
}

// Pixel shader...
const Texture textureHeap[];

struct VertexIn // Matching vertex shader output struct layout
{
    float32x2 uv;
};

PixelOut main(const VertexIn &vertex, const DataPixel* data)
{
    Texture texture = textureHeap[data->textureIndex];
    Sampler sampler = {.minFilter = LINEAR, .magFilter = LINEAR};

    float32x4 color = sample(texture, sampler, vertex.uv);
    return { .color = color };
}

Our goal was to reduce the PSO permutation explosion by minimizing the remaining state inside the PSO. The depth-stencil can be separated on all architectures. The blend state separation is possible on desktop hardware, but most mobile hardware burns the blend equation at the end of the pixel shader microcode. Exposing the framebuffer fetch intrinsics directly to the user is a much better idea than Vulkan’s failed subpass approach. Users can write their own blend formulas unlocking new rendering algorithms, or they can author general parametrized blending formulas to reduce the PSO count.

Indirect drawing

Standard draw/dispatch commands utilize C/C++ function parameters to provide the arguments: thread group dimensions, index count, instance count, etc. Indirect draw calls allow the user to provide a GPU buffer + offset pair instead as the draw argument source, a crucial addition enabling GPU-driven rendering. Our version uses a single GPU pointer instead of the usual buffer object + offset pair, simplifying the API slightly.

gpuDispatchIndirect(commandBuffer, data.gpu, arguments.gpu);
gpuDrawIndexedInstancedIndirect(commandBuffer, dataVertex.gpu, dataPixel.gpu, arguments.gpu);

All of our arguments are GPU pointers. Both the data and the arguments are indirect. This is a great improvement over existing APIs. DirectX 12, Vulkan and Metal don’t support indirect root arguments. The CPU has to provide them.

Indirect multidraw (MDI) should also be supported. The draw count comes from a GPU address. MDI parameters are: an array of root data (GPU pointer, for both vertex and pixel), an array of draw arguments (GPU pointer), and stride for the root data array (for both vertex and pixel). Stride = 0 naturally means that the same root data is replicated for each draw.

gpuDrawIndexedInstancedIndirectMulti(commandBuffer, dataVertex.gpu, sizeof(DataVertex), dataPixel.gpu, sizeof(DataPixel), arguments.gpu, drawCount.gpu);

Vulkan’s multidraw doesn’t allow changing bindings per draw call. You can use gl_DrawID to index into a buffer which contains your draw data structs. This adds an indirection in the shader. You need to use either descriptor indexing or the new descriptor buffer extension to fetch textures. DirectX 12 ExecuteIndirect has a configurable command signature, allowing the user to manually setup a root constant per draw, but this doesn’t hit the fast path on all GPU command processors. ExecuteIndirect tier 1.1 (2024) added a new optional counter increment feature: D3D12_INDIRECT_ARGUMENT_TYPE_INCREMENTING_CONSTANT. This can be used to implement draw ID. SM6.8 (2024) finally added support for SV_StartInstanceLocation, allowing the user to directly embed a constant in the indirect draw arguments. Unlike SV_InstanceID, the new SV_StartInstanceLocation is uniform across the whole draw call, providing optimal codegen for indexed loads (uniform/scalar path). The data fetch still requires an indirection. GPU-generated root data is not supported.

If we generate draw arguments or root data on the GPU, we need to ensure that the command processor waits for the dispatch to finish. Modern command processors prefetch commands and their arguments to hide the latency. We have a flag in our barrier to prevent this. The best practice is to batch update all your draw arguments and root data to avoid fine-grained barriers.

gpuBarrier(commandBuffer, STAGE_COMPUTE, STAGE_COMPUTE, HAZARD_DRAW_ARGUMENTS);

The lack of indirect shader selection is a significant limitation in the current PC and mobile graphics APIs. Indirect shader selection can be implemented using multi-pipelines similar to ray-tracing. Metal also supports indirect command creation (Nvidia has a similar Vulkan extension). An efficient way to skip over draw calls is a valuable subset. DirectX work graphs and CUDA dynamic parallelism allow a shader to spawn more waves on demand. Unfortunately, the APIs to access these hardware improvements is still highly platform specific and scattered in multiple shader entry points. There’s no clear standardization. My followup post will discuss the shader framework and cover this topic in depth.

Our proposed design makes indirect drawing extremely powerful. Both the shader root data and the draw parameters can be indirectly provided by the GPU. These advantages power up multi-draw, allowing clean and efficient per-draw data bindings with no hacks. The future of indirect drawing and the shader framework will be discussed in a followup post.

Render passes

The rasterizer hardware needs to be prepared for rendering before we can start drawing. Common operations include binding render target and depth-stencil views and clearing color and depth. Clear might trigger a fast clear elimination if the clear color is changed. This is transparently handled by the clear command. On mobile GPUs, tiles are stored from on-chip storage to VRAM during rendering. Vulkan, Metal and WebGPU use render pass abstraction for clearing, loading and storing the render target. DirectX 12 added render pass support in the 2018 update in order to optimize rendering on the latest Intel (Gen11) and the Qualcomm (Adreno 630) GPUs. The render pass abstraction doesn’t add notable API complexity, so it's an easy choice for a modern cross platform API.

DirectX12 has render target views and depth-stencil views, and separate descriptor heaps to store them. This is just an API abstraction. These heaps are simply CPU memory allocated by the driver. Render target and depth-stencil views are not GPU descriptors. The rasterizer API is not bindless. The CPU driver sets up the rasterizer using command packets. In Vulkan and Metal you pass the existing texture/view objects to the beginRenderPass directly. The driver gets the required information from the texture object behind the scenes. Our proposed GpuTexture object fits this job. Rasterization output is the main reason we still need a CPU-side texture object. We write texture descriptors directly into GPU memory. The CPU side driver can’t access those.

GpuRenderPassDesc renderPassDesc =
{
    .depthTarget = {.texture = deptStencilTexture, .loadOp = CLEAR, .storeOp = DONT_CARE, .clearValue = 1.0f},
    .stencilTarget = {.texture = deptStencilTexture, .loadOp = CLEAR, .storeOp = DONT_CARE, .clearValue = 0},
    .colorTargets =
    {
        {.texture = gBufferColor, .loadOp = LOAD, .storeOp = STORE, .clearColor = {0,0,0,0}},
        {.texture = gBufferNormal, .loadOp = LOAD, .storeOp = STORE, .clearColor = {0,0,0,0}},
        {.texture = gBufferPBR, .loadOp = LOAD, .storeOp = STORE, .clearColor = {0,0,0,0}}
    }
};

gpuBeginRenderPass(commandBuffer, renderPassDesc);
// Add draw calls here!
gpuEndRenderPass(commandBuffer);

It would be nice to have bindless render passes, bindless/indirect (multi-)clear commands, indirect scissor/viewport rectangles (array), etc. Unfortunately many GPUs today still need the CPU driver to set up their rasterizer.

A note about barriers: Render pass begin/end commands don’t automatically emit barriers. The user can render multiple render passes simultaneously, if they write to disjoint render targets. A barrier between the raster output stage (or later) and the consumer stage will flush the tiny ROP caches if the GPU architecture needs it. Not having an automatic barrier between the render passes is also crucial for efficient depth prepass implementations (ROP caches are not flushed needlessly).

GPU-based clay simulation and ray-tracing tech in Claybook (Sebastian Aaltonen, GDC 2018): I optimized the Unreal Engine 4 console barrier implementations (Xbox One, PS4) to allow render target overlap. The barrier stall is avoided.

Prototype API

My prototype API fits in one screen: 150 lines of code. The blog post is titled “No Graphics API”. That’s obviously an impossible goal today, but we got close enough. WebGPU has a smaller feature set and features a ~2700 line API (Emscripten C header). Vulkan header is ~20,000 lines, but it supports ray-tracing, and many other features our minimalistic API doesn’t yet support. We didn’t have to trade off performance to achieve the reduction in API complexity. For this feature set, our API offers more flexibility than existing APIs. A fully extended summer 2025 Vulkan 1.4 can do all the same things in practice, but is significantly more complex to use and has more API overhead.

// Opaque handles
struct GpuPipeline;
struct GpuTexture;
struct GpuDepthStencilState;
struct GpuBlendState;
struct GpuQueue;
struct GpuCommandBuffer;
struct GpuSemaphore;

// Enums
enum MEMORY { MEMORY_DEFAULT, MEMORY_GPU, MEMORY_READBACK };
enum CULL { CULL_CCW, CULL_CW, CULL_ALL, CULL_NONE };
enum DEPTH_FLAGS { DEPTH_READ = 0x1, DEPTH_WRITE = 0x2 };
enum OP { OP_NEVER, OP_LESS, OP_EQUAL, OP_LESS_EQUAL, OP_GREATER, OP_NOT_EQUAL, OP_GREATER_EQUAL, OP_ALWAYS }; 
enum BLEND { BLEND_ADD, BLEND_SUBTRACT, BLEND_REV_SUBTRACT, BLEND_MIN, BLEND_MAX };
enum FACTOR { FACTOR_ZERO, FACTOR_ONE, FACTOR_SRC_COLOR, FACTOR_DST_COLOR, FACTOR_SRC_ALPHA, ... };
enum TOPOLOGY { TOPOLOGY_TRIANGLE_LIST, TOPOLOGY_TRIANGLE_STRIP, TOPOLOGY_TRIANGLE_FAN };
enum TEXTURE { TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_CUBE, TEXTURE_2D_ARRAY, TEXTURE_CUBE_ARRAY };
enum FORMAT { FORMAT_NONE, FORMAT_RGBA8_UNORM, FORMAT_D32_FLOAT, FORMAT_RG11B10_FLOAT, FORMAT_RGB10_A2_UNORM, ... };
enum USAGE_FLAGS { USAGE_SAMPLED, USAGE_STORAGE, USAGE_COLOR_ATTACHMENT, USAGE_DEPTH_STENCIL_ATTACHMENT, ... };
enum STAGE { STAGE_TRANSFER, STAGE_COMPUTE, STAGE_RASTER_COLOR_OUT, STAGE_PIXEL_SHADER, STAGE_VERTEX_SHADER, ... };
enum HAZARD_FLAGS { HAZARD_DRAW_ARGUMENTS = 0x1, HAZARD_DESCRIPTORS = 0x2, , HAZARD_DEPTH_STENCIL = 0x4 };
enum SIGNAL { SIGNAL_ATOMIC_SET, SIGNAL_ATOMIC_MAX, SIGNAL_ATOMIC_OR, ... };

// Structs
struct Stencil 
{
    OP test = OP_ALWAYS,
    OP failOp = OP_KEEP;
    OP passOp = OP_KEEP;
    OP depthFailOp = OP_KEEP;
    uint8 reference = 0;
};

struct GpuDepthStencilDesc 
{
    DEPTH_FLAGS depthMode = 0;
    OP depthTest = OP_ALWAYS;
    float depthBias = 0.0f;
    float depthBiasSlopeFactor = 0.0f;
    float depthBiasClamp = 0.0f;
    uint8 stencilReadMask = 0xff;
    uint8 stencilWriteMask = 0xff;
    Stencil stencilFront;
    Stencil stencilBack;
};

struct GpuBlendDesc
{
    BLEND colorOp = BLEND_ADD,
    FACTOR srcColorFactor = FACTOR_ONE;
    FACTOR dstColorFactor = FACTOR_ZERO;
    BLEND alphaOp = BLEND_ADD;
    FACTOR srcAlphaFactor = FACTOR_ONE;
    FACTOR dstAlphaFactor = FACTOR_ZERO;
    uint8 colorWriteMask = 0xf;
};

struct ColorTarget {
    FORMAT format = FORMAT_NONE;
    uint8 writeMask = 0xf;
};

struct GpuRasterDesc
{
    TOPOLOGY topology = TOPOLOGY_TRIANGLE_LIST;
    CULL cull = CULL_NONE;
    bool alphaToCoverage = false;
    bool supportDualSourceBlending = false;
    uint8 sampleCount = 1;
    FORMAT depthFormat = FORMAT_NONE;
    FORMAT stencilFormat = FORMAT_NONE;
    Span<ColorTarget> colorTargets = {};
    GpuBlendDesc* blendstate = nullptr; // optional embedded blend state
};

struct GpuTextureDesc
{ 
    TEXTURE type = TEXTURE_2D;
    uint32x3 dimensions;
    uint32 mipCount = 1;
    uint32 layerCount = 1;
    uint32 sampleCount = 1;
    FORMAT format = FORMAT_NONE; 
    USAGE_FLAGS usage = 0;
};

struct GpuViewDesc 
{
    FORMAT format = FORMAT_NONE;
    uint8 baseMip = 0;
    uint8 mipCount = ALL_MIPS;
    uint16 baseLayer = 0;
    uint16 layerCount = ALL_LAYERS;
};

struct GpuTextureSizeAlign { size_t size; size_t align; };
struct GpuTextureDescriptor { uint64[4] data; };

// Memory
void* gpuMalloc(size_t bytes, MEMORY memory = MEMORY_DEFAULT);
void* gpuMalloc(size_t bytes, size_t align, MEMORY memory = MEMORY_DEFAULT);
void gpuFree(void *ptr);
void* gpuHostToDevicePointer(void *ptr);

// Textures
GpuTextureSizeAlign gpuTextureSizeAlign(GpuTextureDesc desc);
GpuTexture gpuCreateTexture(GpuTextureDesc desc, void* ptrGpu);
GpuTextureDescriptor gpuTextureViewDescriptor(GpuTexture texture, GpuViewDesc desc);
GpuTextureDescriptor gpuRWTextureViewDescriptor(GpuTexture texture, GpuViewDesc desc);

// Pipelines
GpuPipeline gpuCreateComputePipeline(ByteSpan computeIR);
GpuPipeline gpuCreateGraphicsPipeline(ByteSpan vertexIR, ByteSpan pixelIR, GpuRasterDesc desc);
GpuPipeline gpuCreateGraphicsMeshletPipeline(ByteSpan meshletIR, ByteSpan pixelIR, GpuRasterDesc desc);
void gpuFreePipeline(GpuPipeline pipeline);

// State objects
GpuDepthStencilState gpuCreateDepthStencilState(GpuDepthStencilDesc desc);
GpuBlendState gpuCreateBlendState(GpuBlendDesc desc);
void gpuFreeDepthStencilState(GpuDepthStencilState state);
void gpuFreeBlendState(GpuBlendState state);

// Queue
GpuQueue gpuCreateQueue(/* DEVICE & QUEUE CREATION DETAILS OMITTED */);
GpuCommandBuffer gpuStartCommandRecording(GpuQueue queue);
void gpuSubmit(GpuQueue queue, Span<GpuCommandBuffer> commandBuffers);

// Semaphores
GpuSemaphore gpuCreateSemaphore(uint64 initValue);
void gpuWaitSemaphore(GpuSemaphore sema, uint64 value);
void gpuDestroySemaphore(GpuSemaphore sema);

// Commands
void gpuMemCpy(GpuCommandBuffer cb, void* destGpu, void* srcGpu,);
void gpuCopyToTexture(GpuCommandBuffer cb, void* destGpu, void* srcGpu, GpuTexture texture);
void gpuCopyFromTexture(GpuCommandBuffer cb, void* destGpu, void* srcGpu, GpuTexture texture);

void gpuSetActiveTextureHeapPtr(GpuCommandBuffer cb, void *ptrGpu);

void gpuBarrier(GpuCommandBuffer cb, STAGE before, STAGE after, HAZARD_FLAGS hazards = 0);
void gpuSignalAfter(GpuCommandBuffer cb, STAGE before, void *ptrGpu, uint64 value, SIGNAL signal);
void gpuWaitBefore(GpuCommandBuffer cb, STAGE after, void *ptrGpu, uint64 value, OP op, HAZARD_FLAGS hazards = 0, uint64 mask = ~0);

void gpuSetPipeline(GpuCommandBuffer cb, GpuPipeline pipeline);
void gpuSetDepthStencilState(GpuCommandBuffer cb, GpuDepthStencilState state);
void gpuSetBlendState(GpuCommandBuffer cb, GpuBlendState state); 

void gpuDispatch(GpuCommandBuffer cb, void* dataGpu, uvec3 gridDimensions);
void gpuDispatchIndirect(GpuCommandBuffer cb, void* dataGpu, void* gridDimensionsGpu);

void gpuBeginRenderPass(GpuCommandBuffer cb, GpuRenderPassDesc desc);
void gpuEndRenderPass(GpuCommandBuffer cb);

void gpuDrawIndexedInstanced(GpuCommandBuffer cb, void* vertexDataGpu, void* pixelDataGpu, void* indicesGpu, uint32 indexCount, uint32 instanceCount);
void gpuDrawIndexedInstancedIndirect(GpuCommandBuffer cb, void* vertexDataGpu, void* pixelDataGpu, void* indicesGpu, void* argsGpu);
void gpuDrawIndexedInstancedIndirectMulti(GpuCommandBuffer cb, void* dataVxGpu, uint32 vxStride, void* dataPxGpu, uint32 pxStride, void* argsGpu, void* drawCountGpu);

void gpuDrawMeshlets(GpuCommandBuffer cb, void* meshletDataGpu, void* pixelDataGpu, uvec3 dim);
void gpuDrawMeshletsIndirect(GpuCommandBuffer cb, void* meshletDataGpu, void* pixelDataGpu, void *dimGpu);

Tooling

How can we debug code that doesn’t bind buffer and texture objects and doesn’t call an API to describe the memory layout explicitly? C/C++ debuggers have been doing that for decades. There’s no special operating system APIs for describing your software’s memory layout. The debugger is able to follow 64-bit pointer chains and use the debug symbol data provided by your compiler. This includes the memory layouts of your structs and classes. CUDA and Metal use C/C++ based shading languages with full 64-bit pointer semantics. Both have robust debuggers that traverse pointer chains without issues. The texture descriptor heap is just GPU memory. The debugger can index it, load a texture descriptor, show the descriptor data and visualize the texels. All of this works already in the Xcode Metal debugger. Click on a texture or a sampler handle in any struct in any GPU address. Debugger will visualize it.

Modern GPUs virtualize memory. Each process has their own page table. The GPU capture has a separate replayer process with its own virtual address space. If the replayer would naively replay all the allocations, it would get a different GPU virtual address for each memory allocation. This was fine for legacy APIs as it wasn’t possible to directly store GPU addresses in your data structures. A modern API needs special replay memory allocation APIs that force the replayer to mirror the exact GPU virtual memory layout. DX12 and Vulkan BDA have public APIs for this: RecreateAt and VkMemoryOpaqueCaptureAddressAllocateInfo. Metal and CUDA debuggers do the same using internal undocumented APIs. A public API is preferable as it allows open source tools like RenderDoc to function.

Don’t raw pointers bring security concerns? Can’t you just read/write other apps' memory? This is not possible due to virtual memory. You can only access your own memory pages. If you accidentally use a stale pointer or overflow, you will get a page fault. Page faults are possible with existing buffer based APIs. DirectX 12 and Vulkan don’t clamp your storage (byteaddress/structured) buffer addresses. OOB causes a page fault. Users can also accidentally free a memory heap and continue using stale buffer or texture descriptors to get a page fault. Nothing really changes. An access to an unmapped region is a page fault and the application crashes. This is familiar to C/C++ programmers. If you want robustness, you can use ptr + size pairs. That’s exactly how WebGPU is implemented. The WebGPU shader compiler (Tint or Naga) emits an extra clamp instruction for each buffer access, including vertex accesses (index buffer value out of bounds). WebGL didn’t allow shading index buffer data with other data. WebGL scanned through the indices on the CPU side (making index buffer update very slow). Back then custom vertex fetch was not possible. The hardware page faulted before the shader even ran.

Translation layers

Being able to run existing software is crucial. Translation layers such as ANGLE, Proton and MoltenVK play a crucial role in the portability and deprecation process of legacy APIs. Let’s talk about translating DirectX 12, Vulkan and Metal to our new API.

MoltenVK (Vulkan to Metal translation layer) proves that Vulkan’s buffer centric API can be translated to Metal’s 64-bit pointer based ecosystem. MoltenVK translates Vulkan’s descriptor sets into Metal’s argument buffers. The generated argument buffers are standard GPU structs containing a 64-bit GPU pointer per buffer binding and a 64-bit texture ID per texture binding. We can do better by allocating a contiguous range of texture descriptors in our texture heap for each descriptor set, and storing a single 32-bit base index instead of a 64-bit texture ID for each texture binding. This is possible since our API has a user managed texture heap unlike Metal.

MoltenVK maps descriptor sets to Metal API root bind slots. We generate a root struct with up to eight 64-bit pointer fields, each pointing to a descriptor set struct (see above). Root constants are translated into value fields and root descriptors (root buffers) are translated into 64-bit pointers. The efficiency should be identical, assuming the GPU driver preloads our root struct fields into uniform/scalar registers (as discussed in the root arguments chapter).

Our API uses 64-bit pointer semantics like Metal. We can use the same techniques employed by MoltenVK to translate the buffer load/store instructions in the shader. MoltenVK also supports translating Vulkan’s new buffer device address extension.

Proton (DX12 to Vulkan translation layer) proves that DirectX 12 SM 6.6 descriptor heap can be translated to Vulkan’s new descriptor buffer extension. Proton also translates other DirectX 12 features to Vulkan. We have already shown that Vulkan to Metal translation is possible with MoltenVK, transitively proving that translation from DirectX 12 to Metal should be possible. The biggest missing feature in MoltenVK is the SM 6.6 style descriptor heap (Vulkan’s descriptor buffer extension). Metal doesn’t expose the descriptor heap directly to the user. Our new proposed API has no such limitation. Our descriptor heap semantics are a superset to SM 6.6 descriptor heap and a close match to Vulkan’s descriptor buffer extension. Translation is straightforward. Vulkan’s extension also adds a special flag for descriptor invalidate, matching our HAZARD_DESCRIPTORS. DirectX 12 descriptor heap API is easy to translate, as it’s just a thin wrapper over the raw descriptor array in GPU memory.

To support Metal 4.0, we need to implement Metal’s driver managed texture descriptor heap. This can be implemented using a simple freelist over our texture heap. Metal uses 64-bit texture handles which are implemented as direct heap indices on modern Apple Silicon devices. Metal allows using the texture handles in shaders directly as textures. This is syntactic sugar for textureHeap[uint64(handle)]. A Metal texture handle is translated into uint64 by our shader translator, maintaining identical GPU memory layout.

Our API doesn’t support vertex buffers. WebGPU doesn’t use hardware vertex buffers either, yet it implements the classic vertex buffer abstraction. WGSL shader translator (Tint or Naga) adds one storage buffer binding per vertex stream and emits vertex load instructions in the beginning of the vertex shader. Custom vertex fetch allows emitting clamp instructions to avoid OOB behavior. A misbehaving website can’t crash the web browser. Our own shader translator adds a 64-bit pointer to the root struct for each vertex stream, generates a struct matching its layout and emits vertex struct load instructions in the beginning of the vertex shader.

We have shown that it’s possible to write translation layers to run DirectX 12, Vulkan and Metal applications on top of our new API. Since WebGPU is implemented on top of these APIs by browsers, we can run WebGPU applications too.

Min spec hardware

Nvidia Turing (RTX 2000 series, 2018) introduced ray-tracing, tensor cores, mesh shaders, low latency raw memory paths, bigger & faster caches, scalar unit, secondary integer pipeline and many other future looking features. Officially PCIe ReBAR support launched with RTX 3000 series, but there exists hacked Turing drivers that support it too, indicating that the hardware is capable of it. This 7 year old GPU supports everything we need. Nvidia just ended GTX 1000 series driver support in fall 2025. All currently supported Nvidia GPUs could be supported by our new API.

AMD RDNA2 (RX 6000 series, 2020) matched Nvidia’s feature set with ray-tracing and mesh shaders. One year earlier, RDNA 1 introduced coherent L2$, new L1$ level, fast L0$, generic DCC read/write paths, fastpath unfiltered loads and a modern SIMD32 architecture. PCIe ReBAR is officially supported (brand name “Smart Access Memory”). This 5 year old GPU supports everything we need. AMD ended GCN driver support already in 2021. Today RDNA 1 & RDNA 2 only receive bug fixes and security updates, RDNA 3 is the oldest GPU receiving game optimizations. All the currently supported AMD GPUs could be supported by our API.

Intel Alchemist / Xe1 (2022) were the first Intel chips with SM 6.6 global indexable heap support. These chips also support ray-tracing, mesh shaders, PCIe ReBAR (discrete) and UMA (integrated). These 3 year old Intel GPUs support everything we need.

Apple M1 / A14 (MacBook M1, iPhone 12, 2020) support Metal 4.0. Metal 4.0 guarantees GPU memory visibility to CPU (UMA on both phones and computers), and allows the user to write 64-bit pointers and 64-bit texture handles directly into GPU memory. Metal 4.0 has a new residency set API, solving a crucial usability issue with bindless resource management in the old useResource/useHeap APIs. iOS 26 still supports iPhone 11. Developers are not allowed to ship apps that require Metal 4.0 just yet. iOS 27 likely deprecates iPhone 11 support next year. On Mac, if you drop Intel Mac support, you have guaranteed Metal 4.0 support. M1-M5 = 5 generations = 5 years.

ARM Mali-G710 (2021) is ARMs first modern architecture. It introduced their new command stream frontend (CSF), reducing the CPU dependency of draw call building and adding crucial features like multi-draw indirect and compute queues. Non-uniform index texture sampling is significantly faster and the AFBC lossless compressor now supports 16-bit floating point targets. G710 supports Vulkan BDA and descriptor buffer extensions and is capable of supporting the new 2025 unified image layout extension with future drivers. The Mali-G715 (2022) introduced support for ray-tracing.

Qualcomm Adreno 650 (2019) supports Vulkan BDA, descriptor buffer and unified image layout extensions, 16-bit storage/math, dynamic rendering and extended dynamic state with the latest Turnip open source drivers. Adreno 740 (2022) introduced support for ray-tracing.

PowerVR DXT (Pixel 10, 2025) is PowerVRs first architecture that supports Vulkan descriptor buffer and buffer device address extensions. It also supports 64-bit atomics, 8-bit and 16-bit storage/math, dynamic rendering, extended dynamic state and all the other features we require.

Conclusion

Modern graphics API have improved gradually in the past 10 years. Six years after DirectX 12 launch, SM 6.6 (2021) introduced the modern global texture heap, allowing fully bindless renderer design. Metal 4.0 (2025) and CUDA have a clean 64-bit pointer based shader architecture with minimal binding API surface. Vulkan has the most restrictive standard, but extensions such as buffer device access (2020), descriptor buffer (2022) and unified image layouts (2025) add support for modern bindless infrastructure, but tools are still lagging behind. As of today, there’s no single API that meets all our requirements, but if we combine their best bits together, we can build the perfect API for modern hardware.

10 years ago, modern APIs were designed for CPU-driven binding models. New bindless features were presented as optional features and extensions. A clean break would improve the usability and reduce the API bloat and driver complexity significantly. It’s extremely difficult to get the whole industry behind a brand new API. I am hoping that vendors are willing to drop backwards compatibility in their new major API versions (Vulkan 2.0, DirectX 13) to embrace the fully bindless GPU architecture we have today. A new bindless API design would solve the mismatch between the API and the game engine RHI, allowing us to get rid of the hash maps and fine grained resource tracking. Metal 4.0 is close to this goal, but it is still missing the global indexable texture heap. A 64-bit texture handle can’t represent a range of textures.

HLSL and GLSL shading languages were designed over 20 years ago as a framework of 1:1 elementwise transform functions (vertex, pixel, geometry, hull, domain, etc). Memory access is abstracted and array handling is cumbersome as there’s no support for pointers. Despite 20 years of existence, HLSL and GLSL have failed to accumulate a library ecosystem. CUDA in contrast is a composable language exposing memory directly and new features (such as AI tensor cores) though intrinsics. CUDA has a broad library ecosystem, which has propelled Nvidia into $4T valuation. We should learn from it.

WebGPU note: WebGPU design is based on 10 year old core Vulkan 1.0 with extra restrictions. WebGPU doesn’t support bindless resources, 64-bit GPU pointers or persistently mapped GPU memory. It feels like a mix between DirectX 11 and Vulkan 1.0. It is a great improvement for web graphics, but doesn’t meet modern bindless API standards. I will discuss WebGPU in a separate blog post.

My prototype API shows what is achievable with modern GPU architectures today, if we mix the best bits from all the latest APIs. It is possible to build an API that is simpler to use than DirectX 11 and Metal 1.0, yet it offers better performance and flexibility than DirectX 12 and Vulkan. We should embrace the modern bindless hardware.

Appendix

A simple user land GPU bump allocator used in all example code. We call gpuHostToDevicePointer once in the temp allocator constructor. We can perform standard pointer arithmetic (such as offset) on GPU pointers. Traditional Vulkan/DX12 buffer APIs require a separate offset. This simplifies the API and user code (ptr vs handle+offset pair). A production ready temp allocator would implement overflow handing (grow, flush, etc).

template<typename T>
struct GPUTempAllocation<T>
{
    T* cpu;
    T* gpu;
}

struct GPUBumpAllocator
{
    uint8 *cpu;
    uint8 *gpu;
    uint32 offset = 0;
    uint32 size;

    TempBumpAllocator(uint32 size) : size(size)
    {
        cpu = gpuMalloc(size);
        gpu = gpuHostToDevicePointer(cpu);
    }

    TempAllocation<uint8> alloc(int bytes, int align = 16)
    {
        offset = alignRoundUp(offset, align);
        if (offset + bytes > size) offset = 0; // Simple ring wrap (no overflow detection)
        TempAllocation<uint8> alloc = { .cpu = cpu + offset, . gpu = gpu + offset };
        offset += bytes;
        return alloc;
    }

    template<typename T> 
    T* alloc(int count = 1)
    {
        TempAllocation<uint8> mem = alloc(sizeof(T) * count, alignof(T));
        return TempAllocation<T> { .cpu = (T*)mem.cpu, . gpu = (T*)mem.gpu };
    }
};

AIPAC Head Hosts Fundraiser for House Candidate Who Swears AIPAC Isn’t Backing Her

Intercept
theintercept.com
2025-12-16 19:19:56
Laura Fine has distanced herself from the Israel lobby, but AIPAC donors are pouring funding into her Illinois congressional campaign. The post AIPAC Head Hosts Fundraiser for House Candidate Who Swears AIPAC Isn’t Backing Her appeared first on The Intercept....
Original Article

The American Israel Public Affairs Committee is not publicly backing any candidate in the race to replace Democratic Rep. Jan Schakowsky in Illinois’s 9th Congressional District. But in private, the group is fundraising for Democratic state Sen. Laura Fine, who has distanced herself from AIPAC and said she isn’t seeking its endorsement.

AIPAC board president Michael Tuchin hosted a private fundraiser for Fine on Monday at his Los Angeles law office, where an Intercept reporter was turned away in the building’s front lobby. “The Intercept should not be here at all,” said a building security guard, relaying a message from fundraiser organizers.

Three people entering the Century City high-rise office, however, confirmed that they were there to attend the Fine fundraiser. An attendee wearing a pin with adjoining U.S. and Israeli flags said she was there for the event and was whisked away by building security when asked why she supported Fine.

After spending years exerting largely unchecked influence over elected U.S. officials, AIPAC appears to be putting more distance between itself and several of its preferred candidates this midterm cycle amid public outrage over Israel’s genocide in Gaza — and as a growing slate of progressive candidates position themselves explicitly against the group. But AIPAC and the broader pro-Israel lobby are still working to shape the next Congress to preserve the U.S.’s diplomatic alliance with Israel and maintain the steady flow of weapons shipments.

The day Fine entered the race in May, Jewish Insider reported that she had met with pro-Israel lobbying groups including AIPAC and Democratic Majority for Israel. The groups did not support Schakowsky, who was instead backed by the more centrist pro-Israel group J Street during her career — meaning the 14-term congresswoman’s retirement represented an opportunity for the lobby to install a more hard-line supporter of Israel.

Fine’s campaign, AIPAC, and Tuchin did not respond to a request for comment.

Fine is running in a crowded Democratic primary field that includes Kat Abughazaleh , a Palestinian American activist who has made her opposition to AIPAC spending and Israel’s genocide a central plank of her campaign; Daniel Biss, the current mayor of Evanston, Illinois; and Bushra Amiwala, a local school board member and activist. Abughazaleh and Biss led the pack in fundraising as of September, according to Federal Election Commission filings, pulling in $1.5 million and $1.3 million respectively. Amiwala has raised $642,000.

Fine had raised just over $660,000 by the same deadline — about half of it from close to 300 donors who AIPAC appears to have directed to her campaign, as the local outlet Evanston Now reported in October. The group sent at least two fundraising emails urging donors in its network to support Fine, after which AIPAC donors poured more than $300,000 into her campaign.

It’s not the first time the group has taken such an approach this cycle, including in Illinois. In the state’s 7th Congressional District, where Democratic Rep. Danny Davis is retiring, AIPAC hasn’t endorsed a replacement — but its donors are funding real estate mogul Jason Friedman, The Intercept reported .

When asked about meeting with AIPAC prior to entering the race, Fine played down her support from the group, telling the university newspaper Loyola Phoenix in October that she was not pursuing its endorsement.

“Senator Fine has not received and is not seeking endorsement from J Street, AIPAC, or any Jewish organization,” her campaign said at the time. “She’s deeply aware of the diversity of political views in the Jewish community and in this district at large. The Senator’s priority is to represent all constituents, bridge divisions, continue standing up against antisemitism wherever it may appear, and continue to represent all members of her district.”

★ Apple TV’s New Fanfare

Daring Fireball
daringfireball.net
2025-12-16 19:08:56
Netflix’s “tadum” is so iconic that it’s the name of their company blog. HBO’s static + chanted om is the OG standard-setter. I suspect the new Apple TV fanfare will be seen in that class. The old one was not....
Original Article

Tim Nudd, writing at Ad Age a few weeks ago (paywalled, alas):

As we mentioned in roundup yesterday, Finneas (aka, Finneas O’Connell) has developed a new sonic logo for Apple TV, the streaming service previously known as Apple TV+. However, the rebrand, created with Apple agency TBWA\Media Arts Lab, goes beyond the audio mnemonics to include a striking new visual look as well.

The visual branding centers on layers of shifting colored light, a metaphor for the range of genres and emotions that Apple TV has cultivated since its 2019 debut.

I held off on posting about this new Apple TV fanfare (a.k.a. sonic logo , a.k.a. mnemonic ) until I’d experienced it a few times, and after a few weeks, watching a bunch of episodes from a few Apple TV series — Mr. Scorsese , a 5-star five-part documentary by Rebecca Miller, absolutely riveting; Pluribus , Vince Gilligan’s excellent new the-less-you-know-about-it-before-you-start-watching- the-better series starring Rhea Seehorn; and The Morning Show season 4, a series that’s skirting just above the good-enough-to-keep-watching line for me — I’m willing to render a verdict.

I love it.

The old one was not bad. But “not bad” should never be good enough for Apple. I can’t find anyone from Apple stating so explicitly, but it seems pretty obvious that the piano chord accompanying the old fanfare was meant to evoke the Macintosh startup chime. That’s a neat idea. And no one is more a fan of the Macintosh than me. I’d argue that the Mac remains the definitive Apple product, the one that best exemplifies everything the company does and should stand for. So harking back to the Macintosh was an interesting idea for the Apple TV fanfare/sonic logo/mnemonic.

But: it just wasn’t great. What makes that chord great for a computer booting up doesn’t make it great for a cinematic sonic logo. Netflix’s “tadum” is so iconic that it’s the name of their company blog . HBO’s static + chanted om is the OG standard-setter. I suspect the new Apple TV fanfare will be seen in that class. The old one was not.

The new one feels like a branding stroke unto itself. Sonically, it doesn’t evoke anything else. It just sounds rich and cool. Visually, with its rotating prism effect, it does evoke the classic six-color Apple logo. Thus, despite moving away from a sonic callback to the Macintosh, the overall effect feels more rooted to Apple’s on-the-cusp-of-a-half-century history. The change makes Apple TV original content feel more like a part of Apple, less like a possible passing fancy (which is what many in Hollywood fear ).

That prism effect was created practically. From a LinkedIn post from Apple’s longtime agency partner TBWA Media Arts Lab (no clue why they posted this on LinkedIn, of all places):

Built from real glass and captured entirely in camera, the new identity explores reflection, color, and light to express the cinematic spirit at the heart of Apple TV. Every shimmer was made for real, no CG shortcuts, a nod to Apple’s belief that craft should be felt, not faked.

The work spans the entire platform, from a sharp five-second show open to a full-length cinematic version for films, paired with a new sonic logo composed by Oscar winner Finneas and a custom typeface, SF TV, developed with Apple’s design team.

They include a very short video showing behind the scenes of its creation. It matters not to me that they photographed this practically, rather than via computer-generated graphics, but the bottom line is that it looks cool, timeless, and Apple-y.

Chris Willman at Variety has an interview with Finneas (O’Connell) regarding the music:

Mnemonic , Finneas says, “is sort of a beautiful word for a logo” accompanied by sound. “The things that I think of as real classic mnemonics are NBC — you can hear that in your head — or HBO has its static.” Finneas is well aware of how modern streaming consumption might make this especially ubiquitous, household by household. “If you’re binge-ing the whole season of Ted Lasso or Severance or Disclaimer ” (the last of those being the limited series that he composed the score for himself), “you’re going to hear the mnemonic 10 times in one day. So it’s gotta be something that’s like the bite of ginger between rolls or something, you know?”

See and hear for yourself. Here’s the old Apple TV mnemonic:

Here’s the new 5-second version, shown at the beginning of each episode of Apple TV original series:

And here’s the full 12-second version, shown before Apple Original Films:

Bravo.

Steinar H. Gunderson: Lichess

PlanetDebian
blog.sesse.net
2025-12-16 18:45:00
I wish more pages on the Internet were like Lichess. It's fast. It feels like it only does one thing (even though it's really more like seven or eight)—well, perhaps except for the weird blogs. It does not feel like it's trying to sell me anything; in fact, it feels like it hardly even wants my mone...
Original Article

I wish more pages on the Internet were like Lichess . It's fast. It feels like it only does one thing (even though it's really more like seven or eight)—well, perhaps except for the weird blogs. It does not feel like it's trying to sell me anything; in fact, it feels like it hardly even wants my money. (I've bought two T-shirts from their Spreadshirt, to support them.) It's super-efficient; I've seen their (public) balance sheets, and it feels like it runs off of a shoestring budget. (Take note, Wikimedia Foundation!) And, perhaps most relieving in this day and age, it does not try to grift any AI.

Yes, I know, chess.com is the juggernaut, and has probably done more for chess' popularity than FIDE ever did. But I still go to Lichess every now and then and just click that 2+1 button. (Generally without even logging in, so that I don't feel angry about it when I lose.) Be more like Lichess.

Too Fast to Think: The Hidden Fatigue of AI Vibe Coding

Hacker News
www.tabulamag.com
2025-12-16 18:32:46
Comments...
Original Article

After vibe coding for some time, I feel fatigue. I’m coding Marvai - a package manager for prompts on my own, with a combination of Claude Code and Cursor.

  • I use Claude Code for code generation, bug fixing , test writing, test fixing, security checks etc.

  • Claude Code is especially useful to fix linting errors from nilaway or staticcheck - for a developer those are boring and tedious.

  • I use Cursor for augmented coding, generate functions, adapt copy&pasted code, for refactoring, fix error handling, and many other tedious tasks.

  • I have been a coder for 40 years and I have seen many tools for developers that haven’t worked, like Model Driven Development MDD/MDA and executable UML.

  • With AI I’m now much faster at generating code and building features than I ever was before. The combination of Claude Code and Cursor is a real speedup.

  • I encountered a new phenomenon.

  • Again and again I feel fatigue. I finish a feature, and another feature, concetrate on reviewing the code the AI generated, and fix a bug and finish a feature with such velocity and I feel fatigue after some hours - sometimes as soon as one hour. AI working at such speed, finishing things to accept or review, feels too much for my brain to process or keep up with. I need to pause for some time before I can start again.

  • I haven’t felt this before as a developer.

  • I first encountered the concept of cognitive load in the book Team Toplogies . The idea there is to structure teams in a way that the cognitive load for developers is not too small and not to big. The more responsibilities a team and it’s members get, the bigger the cognitive load. And if you put many different topics on a team, the cognitive load for the team becomes too big for the team to work.

  • As a young adult I was working in a plastic factory, sitting at a machine. The machine produced vacuum cleaner cases, had it’s rhythm, it finished vacuum cleaner cases on it’s own schedule, made a “PING” when finished, opened the door and I had to grab the casing and put it down (and package it in fine paper etc. which took some time). The machine would close while I was finishing the casing. And for some time it was stressful, working to the rhythm of the machine. Then I got accustomed to the speed and rhythm, until my boss increased the frequency. Living by machine time is what I sometimes feel with Vibe Coding and Cursor generating code or Claude fixing a bug .

  • I had waiting times with compiling and waited for the machine to finish, but it feels differently, with vibe coding it feels like the machine is in control not me.

  • With traditional coding, the speed of your output matches the complexity of the task and the speed of your coding. This gives your brain time to process what is happening. With vibe coding the coding happens so fast, that my brain can’t process what is happening in real time, and thoughts are getting clogged up. Complex tasks are compressed into seconds or minutes.

  • My brain does not get the baking time to mentally process architecture, decisions and edge cases the AI creates - not enough time to put the AI output into one coherent picture. I’m running a marathon at the pace of a sprint - speeds don’t match.

  • One reason developers are developers is the dopamine loop.

  • You write code, it doesn’t work, you fix it, it works, great! Dopamine rush. Several dozens or a hundred times a day. Now this loop speeds up. Faster and faster we run around that loop, and get washed with Dopamine - and your brain gets overwhelmed. And stress hormones at the same time! You get fatigue - instead of the usually happiness and satisfaction of coding.

  • With coding there is a limit to context switching. A context switch in coding is like dumping the cache of your brain and reloading the cache of your brain with a new context. This takes time and energy. You need to build a mental model of the code , to decide what to change and how to change it and then writing the changes out into source code, the essence of coding.

  • With vibe coding the frequency of content switches speeds up tremendously - with the AI fixing and creating many different things in different packages or modules with one go. Even when I <tab>, <tab>, <tab> in Cursor, each change is a micro-content switch from function to function.

  • Each context switch takes energy, every context switch is heavy lifting for your brain. Normally this materializes as the fact that it takes time to context switch. With AI in the driver seat, context switches are forced on you faster and faster.

  • When each context switch takes energy, fast energy switches from feature delivered to feature delivered, vibe coding drains your energy - fatigue!

  • With AI it seems we all become managers, we all become reviewers. The core of the role is changing from turning requirements into code to managing AI output - more like a team lead manages the output of a team, but on a much deeper level. Your responsibility grows to manage a team of five with vibe coding, while still being a developer being responsible for the code. It’s like being a traffic officer in the middle of a busy intersection - which is a stressful job on it’s own - while also overseeing five intersections in parallel.

  • Reviewing, directing and guiding an AI puts more stress on you than writing code, where your writing matches your thinking and doesn’t jump ahead, with you in a rush to catch up.

  • What can be said:

    • Me and many more I assume feel fatigue from vibe coding

    • We need deliberate pacing when working with AI tools

    • We need AI-aware retrospectives to understand what is going on - perhaps having a daily retrospective to get the mind and the code in sync again

    • We need to be aware of new mental health challenges for AI coders

    • We might need to let go of micro managing AIs and trust the AI more - stop trying to bridge the gap between managing an AI and controlling it’s output

  • I don’t think we’ve figured out yet where this is going. AI has made us faster than we’ve ever been, but our brains haven’t caught up to the pace. We’re like early pilots flying with autopilot—capable, but drained. We need new rhythms, new boundaries, and new ways of thinking about what it means to “code.”

  • Maybe the future of coding isn’t just faster. Maybe it’s also slower in a way, on purpose.

  • IP.THC.ORG - Reverse-DNS, Subdomain and CNAME Lookups

    Lobsters
    ip.thc.org
    2025-12-16 18:10:40
    Comments...

    GPT Image 1.5

    Hacker News
    openai.com
    2025-12-16 18:07:07
    Comments...

    Hell Gate's 2025 Last-Minute Gift Guide

    hellgate
    hellgatenyc.com
    2025-12-16 17:50:36
    Clock's a-ticking, but don't worry, the tastemakers of Hell Gate have got you covered....
    Original Article

    It's the most wonderful time of the year—the panic-inducing week when you realize you somehow once again forgot to buy a gift for Aunt Tina (ugh)/your dogwalker (yes, that's how much your dog loves her)/your college best friend who lives across the country now and has three kids but every year still gets you the most thoughtful present (why!!!).

    Don't worry, Hell Gate has got you covered. Until Sunday, December 21, you can buy a discounted Supporter gift subscription (that comes with the beloved Hell Gate hat!) during our Hats for the Holidays sale . You're welcome, Aunt Tina!

    If you're still looking for some last-minute gifts after taking advantage of our big sale on gift subscriptions , here are the best recommendations from Hell Gate's very discerning staff. (We love seltzer, what can we say...)

    Note: Like last year, these are not affiliate links. Not because we don't like money, just because we forgot to figure out how to do that.

    An unnecessarily sleek tool kit

    Recommended for: your friend whose wardrobe is 90 percent COS and just bought an IKEA RIMFORSA work bench

    Give us your email to read the full story

    Sign up now for our free newsletters.

    Sign up

    🪪 Age Verification Is Coming for the Internet | EFFector 37.18

    Electronic Frontier Foundation
    www.eff.org
    2025-12-16 17:44:41
    The final EFFector of 2025 is here! Just in time to keep you up-to-date on the latests happenings in the fight for privacy and free speech online. In this latest issue, we're sharing how to spot sneaky ALPR cameras at the U.S. border, covering a host of new resources on age verification laws, and ex...
    Original Article

    The final EFFector of 2025 is here! Just in time to keep you up-to-date on the latests happenings in the fight for privacy and free speech online.

    In this latest issue , we're sharing how to spot sneaky ALPR cameras at the U.S. border, covering a host of new resources on age verification laws , and explaining why AI companies need to protect chatbot logs from bulk surveillance.

    Prefer to listen in? Check out our audio companion, where EFF Activist Molly Buckley explains our new resource explaining age verification laws and how you can fight back . Catch the conversation on YouTube or the Internet Archive .

    LISTEN TO EFFECTOR

    EFFECTOR 37.18 - 🪪 AGE VERIFICATION IS COMING FOR THE INTERNET

    Since 1990 EFF has published EFFector to help keep readers on the bleeding edge of their digital rights. We know that the intersection of technology, civil liberties, human rights, and the law can be complicated, so EFFector is a great way to stay on top of things. The newsletter is chock full of links to updates, announcements, blog posts, and other stories to help keep readers—and listeners—up to date on the movement to protect online privacy and free expression.

    Thank you to the supporters around the world who make our work possible! If you're not a member yet, join EFF today to help us fight for a brighter digital future.

    AI is wiping out entry-level tech jobs, leaving graduates stranded

    Hacker News
    restofworld.org
    2025-12-16 17:37:41
    Comments...
    Original Article

    In 2022, Rishabh Mishra joined a high-ranking engineering college in India’s Jabalpur with the most predictable dream in global tech: study computer science, write code, and one day make it to Silicon Valley.

    Three years later, Mishra faces a sobering reality.

    Artificial intelligence has gutted entry-level roles in the tech industry that Mishra and his classmates were counting on. Among his 400 classmates at the Indian Institute of Information Technology, Design and Manufacturing, fewer than 25% have secured job offers. His course ends in May 2026, and there’s a sense of panic on the campus.

    Listen: Rishabh Mishra describes how the reality of tech jobs is very different from what he was told

    “It is really bad out there,” Mishra told Rest of World. “Everyone is so panicked — even our juniors. As the degree end nears, the anxiety is heightened among all of us.” Some of his classmates are exploring the option of pursuing higher studies before entering the job market. “But after one year, if you return to the job market, your degree is even more irrelevant,” he said.

    Students at engineering colleges in India, China, Dubai, and Kenya are facing a “jobpocalypse” as artificial intelligence replaces humans in entry-level roles. Tasks once assigned to fresh graduates, such as debugging, testing, and routine software maintenance, are now increasingly automated.

    Over the last three years, the number of fresh graduates hired by big tech companies globally has declined by more than 50%, according to a report published by SignalFire, a San Francisco-based venture capital firm. Even though hiring rebounded slightly in 2024, only 7% of new hires were recent graduates. As many as 37% of managers said they’d rather use AI than hire a Gen Z employee.

    “As demand for junior roles declines, even highly credentialed engineering graduates are struggling to break into tech, especially at the Big Tech companies,” the report said.

    Even highly credentialed engineering graduates are struggling to break into tech.”

    Indian IT services companies have reduced entry-level roles by 20%–25% thanks to automation and AI, consulting firm EY said in a report last month . Job platforms like LinkedIn, Indeed, and Eures noted a 35% decline in junior tech positions across major EU countries during 2024.

    The World Economic Forum’s Future of Jobs Report 2025 warned that 40% of employers expect to reduce staff where AI can automate tasks.

    “Five years ago, there was a real war for [coders and developers]. There was bidding to hire,” and 90% of the hires were for off-the-shelf technical roles, or positions that utilize ready-made technology products rather than requiring in-house development, said Vahid Haghzare, director at IT hiring firm Silicon Valley Associates Recruitment in Dubai .

    Since the rise of AI, “it has dropped dramatically,” he said. “I don’t even think it’s touching 5%. It’s almost completely vanished.” The company headhunts workers from multiple countries including China, Singapore, and the U.K.

    While high-paying jobs at coveted brands like Apple, Microsoft, Amazon, and Meta rarely cross his desk these days, companies that hire recent engineering graduates expect them to execute “additional responsibilities,” like managing a project or leading sales. “They have to face the customer and have customer communications and maybe even do some selling,” Haghzare said.

    Some engineering students have realigned their ambitions to meet such demands from employers. Nishant Kaushik, who studied computer science at another well-ranked college in eastern India, has decided to look for roles in sales or marketing.

    The rise of AI has also rendered engineering degrees less relevant: Workplace demands now differ from what is taught in colleges.

    When Rita Sande Lukale enrolled in an electronics engineering program at the Technical University of Kenya in 2021, she hoped to land a role in the system architecture sector after graduation. Over the past few years, however, she has seen such roles disappear.

    Listen: Rita Sande Lukale describes how AI has replaced humans in simple repetitive tasks.

    Entry-level jobs such as handling data logging, system diagnostics, or code writing have been replaced by AI, Lukale told Rest of World . Now, fresh graduates “must possess higher-level skills, necessary to understand algorithms and use the engineering judgement to troubleshoot the complex and automated systems,” she said.

    While she doesn’t consider AI to be a “job destroyer,” it has fundamentally changed the type of engineers that companies need to hire, Lukale said. She feels she needs to adapt and learn more to land a job.

    Not only are fresh graduates expected to understand and use the latest tools efficiently, “they are asked to up their output by 70% because ‘they are using AI,’” Liam Fallon, who heads the product division at GoodSpace AI, an AI-powered recruiting company, told Rest of World . As a result, students face a rapidly changing industry that requires them to upskill outside the curriculum on their own. Experts believe universities are unable to align their academic practices fast enough to meet AI-driven industry demands.

    The current system, where a student commits three to five years to learn computer science and then looks for a job, is “not sustainable,” Haghzare said. Students are “falling down a hole, and they don’t know how to get out of it.”

    The GitHub Actions control plane is no longer free

    Hacker News
    www.blacksmith.sh
    2025-12-16 17:37:34
    Comments...
    Original Article

    TL;DR

    GitHub is adding a $0.002-per-minute fee on all GitHub Actions usage, so the control plane is no longer free.

    What's happening?

    GitHub just announced changes to Actions pricing. Previously, GitHub Actions had a free control plane. That meant if you used GitHub Actions but ran jobs outside of GitHub-hosted runners, whether that’s on Blacksmith, on your own machines, or in your own AWS account, you paid nothing to GitHub for those minutes; you only paid for the compute.

    With this change, GitHub is introducing a $0.002 per-minute platform fee for all GitHub Actions usage.

    In practice, this means CI costs now have two components:

    • Compute costs (whoever runs your runners)
    • A flat GitHub platform fee, charged per minute of Actions usage

    These changes go into effect on March 1st, 2026.

    Our perspective on why they’re making these changes

    GitHub Actions has long had a graduation churn problem. As companies grow, their CI workloads become larger, more complex, and more expensive. At a certain scale, GitHub-hosted runners become both slow and costly, pushing teams to self-host or move to third-party runners like Blacksmith.

    Until now, that shift had an important side effect: companies could continue using the GitHub Actions control plane while paying GitHub nothing for CI execution. GitHub provided scheduling, orchestration, and workflow automation, but captured no revenue from some of its largest and fastest-growing customers.

    The new per-minute platform fee changes that. It directly monetizes the Actions control plane and establishes a floor on what GitHub earns from CI, regardless of where jobs run. In effect, self-hosting is no longer free.

    At the same time, GitHub reduced the price of GitHub-hosted runners. This isn’t accidental. Lower hosted runner prices make GitHub-hosted runners more attractive, while the platform fee introduces a new, unavoidable cost for self-hosting.

    From GitHub’s perspective, this is a rational move. Most Actions usage is concentrated on smaller runners, so the hosted runner price cuts likely don’t materially impact revenue. More importantly, GitHub is trading lower-margin compute revenue for higher-margin platform revenue.

    Hosted runners are fundamentally a compute business. The platform fee, by contrast, monetizes software without scaling infrastructure costs linearly. As CI usage grows, that revenue scales with significantly better unit economics.

    In the past, our customers have asked us how GitHub views third-party runners long-term. The platform fee largely answers that: GitHub now monetizes Actions usage regardless of where jobs run, aligning third-party runners like Blacksmith as ecosystem partners rather than workarounds.

    Per-minute CI pricing and its impact on self-hosting

    Before this change, self-hosting was a way to avoid paying GitHub entirely. That’s no longer true. Now, self-hosting retains the operational burden of running CI infrastructure while still incurring per-minute charges on GitHub.

    At that point, the primary variable you can still control is how many minutes your CI jobs consume. One approach is to run CI on infrastructure designed to minimize wall-clock time and eliminate redundant work. That’s the problem Blacksmith focuses on. In practice, this shows up in a few areas:

    • Faster machines. Blacksmith runs CI jobs on CPUs that have 50%+ higher single-core performance than GitHub-hosted runners. As part of ongoing fleet upgrades, we’re deploying even newer instances that add an additional 15–25% improvement, further reducing runtime for CPU-bound workloads.
    • Reusing work across runs. Docker layer caches are persisted across CI runs, allowing unchanged layers to be reused rather than rebuilt, cutting Docker build times from tens of minutes to seconds for many customers.
    • Container caching (beta). Service containers can be pre-hydrated on runners, removing repeated image pulls and extraction from the job startup path.

    With a per-minute platform fee, CI performance and cost are tightly coupled. The remaining lever is reducing CI time and total Actions.

    GitHub will begin charging for self-hosted action runners on March 2026

    Hacker News
    github.blog
    2025-12-16 17:32:38
    Comments...
    Original Article

    On January 1, 2026 , GitHub will reduce the price of GitHub-hosted runners by up to 39% depending on the machine type used . The free usage minute quotas will remain the same.

    On March 1, 2026, GitHub will introduce a new $0.002 per minute GitHub Actions cloud platform charge that will apply to self-hosted runner usage. Any usage subject to this charge will count toward the minutes included in your plan, as explained in our GitHub Actions billing documentation .

    Runner usage in public repositories will remain free. There will be no changes in price structure for GitHub Enterprise Server customers.

    Deeper investment in the Actions self-hosted experience

    We are increasing our investment into our self-hosted experience to ensure that we can provide autoscaling for scenarios beyond just Linux containers. This will include new approaches to scaling, new platform support, Windows support, and more as we move through the next 12 months.

    For more details about the product investments we’re making in Actions, please visit our Executive Insights page .

    Texas sues TV makers for taking screenshots of what people watch

    Bleeping Computer
    www.bleepingcomputer.com
    2025-12-16 17:29:22
    The Texas Attorney General sued five major television manufacturers, accusing them of illegally collecting their users' data by secretly recording what they watch using Automated Content Recognition (ACR) technology. [...]...
    Original Article

    TV remote

    The Texas Attorney General sued five major television manufacturers, accusing them of illegally collecting their users' data by secretly recording what they watch using Automated Content Recognition (ACR) technology.

    The lawsuits target Sony , Samsung , LG , and China-based companies Hisense and TCL Technology Group Corporation. Attorney General Ken Paxton's office also highlighted "serious concerns" about the two Chinese companies being required to follow China's National Security Law, which could give the Chinese government access to U.S. consumers' data.

    According to complaints filed this Monday in Texas state courts, the TV makers can allegedly use ACR technology to capture screenshots of television displays every 500 milliseconds, monitor the users' viewing activity in real time, and send this information back to the companies' servers without the users' knowledge or consent.

    Wiz

    Paxton's office described ACR technology as "an uninvited, invisible digital invader" designed to unlawfully collect personal data from smart televisions, alleging that the harvested information then gets sold to the highest bidder for ad targeting.

    "Companies, especially those connected to the Chinese Communist Party, have no business illegally recording Americans' devices inside their own homes," Paxton said .

    "This conduct is invasive, deceptive, and unlawful. The fundamental right to privacy will be protected in Texas because owning a television does not mean surrendering your personal information to Big Tech or foreign adversaries."

    Spokespersons for Sony, Samsung, Hisense, and TCL were not immediately available for comment when contacted by BleepingComputer earlier today.

    An LG spokesperson told BleepingComputer that, "As a matter of policy, LG Electronics USA does not generally comment on pending legal matters such as this."

    Almost a decade ago, in February 2017, Walmart-owned smart TV manufacturer Vizio paid $2.2 million to settle charges brought by the U.S. Federal Trade Commission and the New Jersey Attorney General that it collected viewing data from 11 million consumers without their knowledge or consent using a "Smart Interactivity feature.

    The two agencies said that since February 2014, Vizio and an affiliated company have manufactured and sold smart TVs (and retrofitted older models by installing tracking software remotely) that captured detailed information on what is being watched, including content from cable, streaming services, and DVDs.

    According to the complaint , Vizio also attached demographic information (such as sex, age, income, and education) to the collected data and sold it to third parties for targeted advertising purposes.

    In August 2022, the FTC published a consumer alert on securing Internet-connected devices, advising Americans to adjust the tracking settings on their smart TVs to protect their privacy.

    Update December 16, 12:43 EST: Added LG statement.

    tines

    Break down IAM silos like Bitpanda, KnowBe4, and PathAI

    Broken IAM isn't just an IT problem - the impact ripples across your whole business.

    This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

    Determinate Nix 3.0

    Lobsters
    determinate.systems
    2025-12-16 17:25:04
    Comments...
    Original Article

    Today, we’re thrilled to announce the release of Determinate Nix 3.0 . Determinate Nix is our professionally maintained, security-focused distribution of Nix designed for organizations that cannot compromise on security, compliance, or performance.

    The version number matters. The Nix project has long intended to release version 3.0 when flakes are stable. With Determinate Nix 3.0, we’ve fulfilled that promise by offering a formal stability guarantee for flakes , making them production ready today.

    Why flake stability matters

    Flake stability is essential for organizations developing mission-critical systems. Although flakes enhance the core features of Nix—reproducible environments, predictable builds, composable configurations—by enforcing pinned dependencies, we continue to see deep uncertainty in the ecosystem due to flakes’ experimental status in upstream Nix. Without such a guarantee, organizations have expressed concerns about unpredictable breaking changes that could disrupt CI/CD pipelines, developer workflows, and production deployments.

    Our flake stability guarantee mitigates this risk, ensuring that your flake-based configurations function reliably through every update and enabling you to confidently adopt flakes for your most important projects today.

    Not a fork, a future-proof foundation

    Determinate Nix 3.0 isn’t a fork of Nix—it’s a downstream distribution that ensures full compatibility with the broader Nix ecosystem while incorporating the governance, security features, and performance optimizations necessary for mission-critical deployments.

    Building a better Nix

    Determinate Nix 3.0 represents a fundamental shift in how we deliver Nix to organizations with mission-critical requirements. We don’t just package upstream Nix—we build it ourselves from source in our secure, SLSA build level 3 , controlled infrastructure. This independent build process is crucial for the trust, security, and stability that regulated environments demand.

    By maintaining our distribution, we can innovate at the pace our customers need without being constrained by upstream development cycles. This means that Determinate Nix customers will soon have immediate access to critical features like:

    • Parallel evaluation of Nix expressions, which can deliver 3-4x faster performance for complex configurations.
    • Lazy trees , which can dramatically improve evaluation speed for large source repositories.

    Our approach combines the best of both worlds: Determinate Nix customers benefit from cutting-edge capabilities today while we maintain compatibility with the broader Nix ecosystem and actively contribute our improvements to upstream Nix, where the community ultimately determines their inclusion. Choosing Determinate Nix gives you priority access to innovations that address real-world needs while ensuring seamless integration with existing systems.

    Security that meets modern standards

    Security is central to every aspect of Determinate Nix and the entire Determinate platform .

    • SOC 2 Type II certified : Our infrastructure meets rigorous compliance standards.
    • Zero-trust security model : Federated authentication combined with fine-grained access controls with federated authentication.
    • Modern authentication : Shift from static secrets to secure, policy-driven identities through Identity and Access Management (IAM) roles and identity providers such as GitHub and Microsoft Entra .
    • Corporate network integration : Automatic certificate handling for ZScaler , Fortinet , and other security platforms.
    • Defined security response : We provide an SLA for vulnerability management, ensuring prompt and predictable security updates.
    • Controlled build environments : We build every component in our security-certified infrastructure, with critical components receiving additional signing and notarization.

    Stability you can rely on

    When your business relies on dependable software delivery, you require predictability and consistency:

    • Flake stability guarantee : While flakes remain experimental in upstream Nix, we provide a formal stability guarantee to ensure your workflows remain functional.
    • Rigorous release process : Every change undergoes comprehensive security, performance, and compatibility validation.
    • Customer roadmap : Transparent decision making and predictable release cycles.

    Deployment options for every need

    From bare metal to virtual machines, cloud to edge, Determinate Nix 3.0 delivers reproducible builds everywhere:

    • First-class macOS support : We provide full MDM integration, including partnerships with leading MDM providers like jamf , and ensure seamless macOS upgrades across your Apple ecosystem.
    • Performance optimizations : Ship code faster with improved build times and streamlined workflows.
    • Intelligent resource management : Automated garbage collection monitors system conditions to optimize maintenance.

    Why organizations choose Determinate Nix

    From financial services to healthcare to critical infrastructure, teams choose Determinate Nix when they require:

    • Predictable feature implementation with clear timelines for new capabilities.
    • Security and compliance that meet and exceed industry requirements.
    • Dramatically faster build times that slash evaluation overhead and accelerate development cycles by 3-4x in typical workloads.
    • Operational workflows that scale from small projects to global deployments.

    Determinate Nix 3.0 transforms Nix from a powerful tool into a trusted platform that delivers the governance, performance, and stability that serious production environments demand.

    Get started with Determinate Nix 3.0 today!

    Ready to experience Determinate Nix 3.0?

    Installing Determinate Nix 3.0

    Installation is straightforward whether you’re deploying across an organization or installing on your workstation. Our comprehensive documentation site provides tailored installation instructions for most environments.

    Upgrading to Determinate Nix 3.0

    Follow these straightforward upgrade instructions for your environment.

    For macOS users

    Download the universal package and run it.

    Logo for graphical installer

    Install Determinate Nix on macOS now 🍎

    With support for Apple Silicon ( aarch64-darwin )

    When the installation is complete, open a terminal and run:

    You should see nix (Determinate Nix 3.0.0) 2.26.3 .

    For NixOS users

    If you’re already using the Determinate flake in your NixOS configuration, update the flake: Update the inputs section flake.nix to reference the latest Determinate version:

    {

    inputs.determinate.url = "https://flakehub.com/f/DeterminateSystems/determinate/*";

    }

    Run a system rebuild to apply the changes:

    sudo nixos-rebuild switch --flake .

    Log in to FlakeHub :

    Verify your upgrade:

    You should see nix (Determinate Nix 3.0.0) 2.26.3 .

    For Linux users

    First, download the appropriate determinate-nixd for your platform:

    Linux (x86_64)

    curl -sSLfo determinate-nixd https://install.determinate.systems/determinate-nixd/stable/x86_64-linux

    Linux (aarch64)

    curl -sSLfo determinate-nixd https://install.determinate.systems/determinate-nixd/stable/aarch64-linux

    Make the file executable and run the upgrade:

    chmod +x ./determinate-nixd

    sudo ./determinate-nixd upgrade

    Log in to FlakeHub :

    The upgrade process will:

    • Preserve all your existing Nix configurations
    • Update to Determinate Nix 3.0 components
    • Restart the Nix daemon with the new version

    Verify your upgrade:

    You should see nix (Determinate Nix 3.0.0) 2.26.3 . You can now remove the temporary installation file:

    For FlakeHub teams, your authentication and access to private flakes and caches will remain intact throughout the upgrade process. If you encounter any issues during the upgrade or have additional questions, enterprise customers should contact their dedicated account representative directly. All users are also welcome to join our Discord server for community support.

    Ready to transform the way your team builds critical software? Experience Determinate Nix 3.0 today and leave behind dependency nightmares, security headaches, and performance bottlenecks. Email hello@determinate.systems to discuss how we can empower your team with a robust foundation that enables you to focus on what matters most: creating exceptional software that drives your business forward.

    FVWM-95

    Hacker News
    fvwm95.sourceforge.net
    2025-12-16 17:13:07
    Comments...
    Original Article


    What is FVWM-95?

    Fvwm95 is a hack based on fvwm2 . It tries to emulate the good features of a well known product without bloating the regular fvwm code.

    The main aspects are:

    • A familiar look and feel. It can be interesting for users moving from the MS-World to Unix, or for those who have to switch regularly between the two. Or for those that simply would like to have the same MS look and feel in Unix, or for those that want to have just another window manager. But before all, it's meant to be useful, simple and efficient.
    • Same flexible and easy configuration as the native fvwm.
    • Functionality extensible via loadable modules.
    • A taskbar: find quickly an application window and don't take space with icon windows.
    Shortly after releasing the first version of fvwm95, we started working on a desktop-folder metaphor for the window manager in order to have a more complete emulation of the Windows-95 desktop. The development evolved towards the creation of a C++ class library , providing an easily extensible set of Win95-looking widgets, which eased the development of new applications.

    Here are some fvwm95 screenshots:


    Downloads

    The main distribution site has moved from mitac11.uia.ac.be to sourceforge. Go to the releases directory.


    Mailing list

    The old mailing list at physik.uni-muenchen.de has been moved to lists.sourceforge.net. The address of the new list is: To subscribe or unsubscribe a message should be sent to: with the word "subscribe" or "unsubscribe" in the message body. The messages will be archived and could be requested from: A weekly (or when 40kByte of size is reached) digest is also available:


    Some fvwm and fvwm95-related links


    Page last updated: Nov 26, 2001.

    Access count since last update:

    Pricing Changes for GitHub Actions

    Hacker News
    resources.github.com
    2025-12-16 17:12:02
    Comments...
    Original Article

    Today we’re announcing updates to our pricing and product models for GitHub Actions.

    Why?

    When we shipped Actions in 2018, we had no idea how popular it would become. By early 2024, the platform was running about 23 million jobs per day and our existing architecture couldn’t reliably support our growth curve. In order to increase feature velocity, we first needed to improve reliability and modernize the legacy frameworks that supported GitHub Actions.

    Our solution was to re-architect the core backend services powering GitHub Actions jobs and runners with the goals of improving uptime and resilience against infrastructure issues, enhancing performance, reducing internal throttles, and leveraging GitHub’s broader platform investments and developer experience improvements. This work is paying off by helping us handle our current scale, even as we work through the last pieces of stabilizing our new platform.

    Since August, all GitHub Actions jobs have run on our new architecture, which handles 71 million jobs per day (over 3x from where we started). Individual enterprises are able to start 7x more jobs per minute than our previous architecture could support.

    As with any product, our goal at GitHub has been to meet customer needs while providing enterprises with flexibility and transparency.

    This change better supports a world where CI/CD must be faster and more reliable, better caching, more workflow flexibility, rock-solid reliability, and strengthens the core experience while positioning GitHub Actions to power GitHub’s open, secure platform for agentic workload.

    What’s changing?

    Lower prices for GitHub-hosted runners

    Starting today, we’re charging fairly for Actions across the board which reduces the price of GitHub Hosted Runners and the price the average GitHub customer pays. And we’re reducing the net cost of GitHub-hosted runners by up to 39% , depending on which machine type is used.

    This reduction is driven by a ~40% price reduction across all runner sizes, paired with the addition of a new $0.002 per-minute GitHub Actions cloud platform charge. For GitHub-hosted runners, the new Actions cloud platform charge is already included into the reduced meter price.

    Standard GitHub-hosted or self-hosted runner usage on public repositories will remain free . GitHub Enterprise Server pricing is not impacted by this change.

    The price reduction you will see in your account depends on the types of machines that you use most frequently – smaller runners will have a smaller relative price reduction, larger runners will see a larger relative reduction.

    This price reduction makes high-performance compute more accessible for both high-volume CI workloads and the agent jobs that rely on fast, secure execution environments.

    For full pricing update details, see the updated Actions runner prices in our documentation .

    This price change will go into effect on January 1, 2026 .

    Introduction of the GitHub Actions cloud platform charge

    We are introducing a $0.002 per-minute Actions cloud platform charge for all Actions workflows across GitHub-hosted and self-hosted runners. The new listed GitHub-runner rates include this charge. This will not impact Actions usage in public repositories or GitHub Enterprise Server customers.

    This aligns pricing to match consumption patterns and ensures consistent service quality as usage grows across both hosting modalities.

    This will impact self-hosted runner pricing starting March 1, 2026.

    Deepened investment in the Actions self-hosted experience

    We are increasing our investment into our self-hosted experience to ensure that we can provide autoscaling for scenarios beyond just Linux containers. This will include new approaches to scaling, new platform support, Windows support, and more as we move through the next 12 months. Here’s a preview of what to expect in the new year:

    GitHub Scale Set Client

    This new client provides enterprises with a lightweight Go SDK to build custom autoscaling solutions without the complexity of Kubernetes or reliance on ARC. It integrates seamlessly with existing infrastructure—containers, virtual machines, cloud instances, or bare metal—while managing job queuing, secure configuration, and intelligent scaling logic. Customers gain a supported path to implement flexible autoscaling, reduce setup friction, and extend GitHub Actions beyond workflows to scenarios such as self-hosted Dependabot and Copilot Coding Agent.

    Multi-label support

    We are reintroducing multi-label functionality for both GitHub-hosted larger runners and self-hosted runners, including those managed by Actions Runner Controller (ARC) and the new Scale Set Client.

    Actions Runner Controller 0.14.0

    This upcoming release introduces major quality-of-life improvements, including refined Helm charts for easier Docker configuration, enhanced logging, updated metrics, and formalized versioning requirements. It also announces the deprecation of legacy ARC, providing a clear migration path to a more reliable and maintainable architecture. Customers benefit from simplified setup, improved observability, and confidence in long-term support, reducing operational friction and improving scalability.

    Actions Data Stream

    The Actions Data Stream will deliver a near real-time, authoritative feed of GitHub Actions workflow and job event data, including metadata such as the version of the action that was executed on any given workflow run. This capability enhances observability and troubleshooting by enabling organizations to integrate event data into monitoring and analytics systems for compliance and operational insights. By providing structured, high-fidelity data at scale, it eliminates reliance on manual log parsing and empowers teams to proactively manage reliability and performance.

    Why this matters

    Agents are expanding what teams can automate—but CI/CD remains the heartbeat of modern software delivery. These updates enable both a faster, more reliable CI/CD experience for every developer, and a scalable, flexible, secure execution layer to power GitHub’s agentic platform.

    Our goal is to ensure GitHub Actions continues to meet the needs of the largest enterprises and of individual developers alike, with clear pricing, stronger performance, and a product direction built for the next decade of software development.

    FAQ

    What are the new GitHub-hosted runner rates?
    See the GitHub Actions runner pricing reference for the updated rates that will go into effect on January 1, 2026. These listed rates include the new $0.002 per-minute Actions cloud platform charge.

    Which job execution scenarios for GitHub Actions are affected by this pricing change?

    • Jobs that run in private repositories and use standard GitHub-hosted or self-hosted runners
    • Any jobs running on larger GitHub-hosted runners

    Standard GitHub-hosted or self-hosted runner usage on public repositories will remain free. GitHub Enterprise Server pricing is not impacted by this change.

    When will this pricing change take effect?

    The price decrease for GitHub-hosted runners will take effect on January 1, 2026. The new charge for self-hosted runners will apply beginning on March 1, 2026. The price changes will impact all customers on these dates.

    Will the free usage quota available in my plan change?
    Beginning March 1, 2026, self-hosted runners will be included within your free usage quota, and will consume available usage based on list price the same way that Linux, Windows, and MacOS standard runners work today.

    Will self-hosted runner usage consume from my free usage minutes?
    Yes, billable self-hosted runner usage will be able to consume minutes from the free quota associated with your plan.

    How does this pricing change affect customers on GitHub Enterprise Server?

    This pricing change does not affect customers using GitHub Enterprise Server. Customers running Actions jobs on self-hosted runners on GitHub Enterprise Server may continue to host, manage, troubleshoot and use Actions on and in conjunction with their implementation free of charge.

    Can I bill my self-hosted runner usage on private repositories through Azure?

    Yes, as long as you have an active Azure subscription ID associated with your GitHub Enterprise or Organization(s).

    What is the overall impact of this change to GitHub customers?

    Of Actions users impacted by this change, 85% will see their Actions bill decrease. Of the 15% who are impacted across all cohorts the median increase is $13.

    Did GitHub consider how this impacts individual developers, not just Enterprise scale customers of GitHub?
    From our individual users (free & Pro plans) of those who used GitHub Actions in the last month in private repos only 0.09% would end up with a price increase, with a median increase of under $2 a month. Note that this impact is after these users have made use of their included minutes in their plans today, entitling them to over 33 hours of included GitHub compute, and this has no impact on their free use of public repos. A further 2.8% of this total user base will see a decrease in their monthly cost as a result of these changes. The rest are unimpacted by this change.

    How can I figure out what my new monthly cost for Actions looks like?

    GitHub Actions provides detailed usage reports for the current and prior year . You can use this prior usage alongside the rate changes that will be introduced in January and March to estimate cost under the new pricing structure. We have created a Python script to help you leverage full usage reports to calculate your expected cost after the price updates.

    We have also updated our Actions pricing calculator , making it easier to estimate your future costs, particularly if your historical usage is limited or not representative of expected future usage.

    Additional resources

    Artie (YC S23) Is Hiring Senior Enterprise AES

    Hacker News
    www.ycombinator.com
    2025-12-16 17:00:57
    Comments...
    Original Article

    Software that streams data from databases to warehouses in real-time

    Senior Enterprise AE

    $300K - $350K 0.10% San Francisco, CA, US

    Connect directly with founders of the best YC-funded startups.

    Apply to role ›

    About the role

    About Artie

    Artie is a fully-managed change data capture (CDC) streaming platform that replicates production databases into data warehouses and lakes - in real time, with zero maintenance. We make high-volume data replication simple, reliable, and scalable for engineering teams.

    Our platform powers mission-critical use cases including fraud and risk monitoring, inventory visibility, customer-facing analytics, and AI/ML workloads.

    We’re trusted by teams like Substack, Alloy, and ClickUp, and backed by top-tier investors including Y Combinator, General Catalyst, Pathlight, and the founders of Dropbox and Mode.

    Artie is built for engineers who care about performance, reliability, and operational simplicity - and we’re growing fast. This role is your chance to shape our GTM from the ground up.

    About the Role

    We’re hiring our first Senior Enterprise AEs to help scale Artie’s sales motion.

    This is not a “run the playbook” role. You’ll refine the playbook - defining what great full-cycle enterprise sales looks like for a deeply technical platform. You’ll partner directly with founders, influence product strategy, and set the bar for future AEs.

    What you’ll do

    • Run full-cycle enterprise sales
      • Own deals end-to-end: sourcing, qualification, discovery, demos, POCs, procurement, and closing
      • Navigate 6-12 month cycles with engineering, data, security, finance, and legal stakeholders
      • Multi-thread deeply and build strong, technical champions
    • Drive technical discovery & solutioning
      • Understand customer architectures and pain points (SQL Server, Postgres, MySQL, Kafka, Snowflake, VPCs, networking)
      • Map these to Artie’s capabilities with clarity and confidence
      • Whiteboard solutions with staff engineers and data architects
    • Lead rigorous evaluations
      • Build structured POC plans
      • Partner with engineering to define success criteria
      • Drive toward clear, mutual action plans
    • Source your own pipeline
      • There is no SDR team - you source 80%+ of pipeline through outbound, events, founder referrals, and creative prospecting
      • Use your curiosity and rigor to start real technical conversations
    • Sell the vision and business value (not features)
      • Translate deep technical concepts (e.g. log-based CDC, Kafka buffering) into ROI, TCO reduction, and platform reliability
      • Inspire our buyers with how Artie can unlock new opportunities for their company

    What we’re looking for

    • Enterprise sales mastery:
      • 5+ years of full cycle AE experience in enterprise or upper/mid-market
      • Consistent track record of closing $100-300K+ ACV deals
      • Comfortable navigating 6-12 month cycles and complex procurement
      • Proven experience run full-cycle deals without SDR or SE support
    • Deep technical fluency:
      • Experience selling dev tools, data infra, or cloud platforms to technical buyers
      • Able to confidently explain concepts like log-based CDC, Kafka, schema evolution, or cloud networking basics (VPCs, peering, security reviews)
      • Comfortable whiteboarding with staff-level engineers and technical stakeholders
      • Fluent discussing database, streaming, and cloud architecture concepts with engineering teams
    • Outbound-first mindset:
      • Self-sourced a significant portion of pipeline in previous roles
      • Consistent and persistent prospector who finds creative ways to engage prospects
    • Extreme ownership:
      • Never drop the ball - internally or externally
      • Drives alignment, writes structured follow-ups, and runs mutual action plans
    • Consultative and curious:
      • Asks layered questions, uncovers deep pain, and guides prospects to clarity and value
    • Collaborative and self-aware:
      • Knows when to pull in help - from CTO deep dives to executive alignment with CEO
      • Works closely with teammates to win complex deals together
      • Willing to work in-person, 5 days/week at our SF office (relocation covered)

    What you’ll get

    • A Seat at the Table: Join as a founding GTM member with real influence on company direction.
    • End-to-End Ownership: Drive the full GTM lifecycle—strategy, execution, and iteration.
    • Tight Product Loop: Collaborate closely with product and leadership to shape what we build and why.

    Compensation & Benefits

    • $150-175K base salary ($300-350K OTE) depending on experience
    • Equity: ~0.1%
    • Healthcare, 401(k), unlimited PTO
    • Lunch & dinner provided
    • Visa sponsorship available

    About the interview

    30min Hiring Manager

    30min Working Session

    Take Home Case Study

    Onsite Interview

    Post-onsite Call

    About Artie

    We are building Artie, a real-time data streaming solution focused on databases and data warehouses. Typical ETL solutions leverage batched processes or schedulers (DAGs, Airflow), which cannot achieve real time data syncs. We leverage change data capture (CDC) and stream processing to perform data transfers in a more efficient way, which enables sub-minute latency.

    Artie

    Founded: 2023

    Batch: S23

    Team Size: 10

    Status: Active

    Location: San Francisco

    Founders

    Track Surveillance (Flock Cameras) Tech in Local Government Meetings

    Hacker News
    alpr.watch
    2025-12-16 16:54:19
    Comments...
    Original Article

    ✓ Link copied! Share this meeting with others.

    Your local government might be discussing surveillance tech like Flock cameras, facial recognition, or automated license plate readers right now. This map helps you find those meetings and take action.

    Beautiful Unethical Dangerous

    Why this matters: Municipalities across the US are quietly adopting surveillance technologies in rapidly growing numbers with over 80,000 cameras already out on the streets. These systems track residents' movements, collect biometric data, and build massive databases of our daily lives.

    alpr.watch scans meeting agendas for keywords like "flock," "license plate reader," "alpr," and more. Each pin on the map shows where these conversations are happening so that you can make a difference.

    Show only upcoming meetings

    Get Email Alerts for Your Area

    Enter your email below and we'll send you a login link. After logging in, you can set your notification preferences.

    ✓ Check your email for a login link!

    ✗ Please enter a valid email address.

    Loading map data

    Fetching meetings...

    🔍 Zoom in to see ALPR surveillance cameras

    Data before mid-December may be unverified. All future submissions are 100% moderator approved.

    Statistics

    -- Local Councils Monitored

    -- Meetings Indexed

    -- Cameras Mapped

    Understanding Mass Surveillance

    What is ALPR?

    Automated License Plate Recognition (ALPR) systems use cameras and artificial intelligence to capture, read, and store license plate data from every passing vehicle.

    These systems work 24/7 creating a massive database of where vehicles, and by extension, people, travel. Every trip to the grocery store, doctor's office, or place of worship gets recorded and stored.

    What is Flock Safety?

    Flock Safety is one of the largest manufacturers of ALPR cameras in the United States, marketing their systems to neighborhoods and law enforcement.

    Flock cameras capture license plates, vehicle make/model, color, and other identifying features. This data is shared across a massive network of agencies and jurisdictions, creating a surveillance web that tracks millions of Americans.

    The Slippery Slope

    History shows that surveillance systems expand beyond their original scope:

    • Systems marketed for "solving crimes" get used for immigration enforcement
    • Temporary programs become permanent infrastructure
    • Data sharing agreements grow to include more agencies
    • Technology advances enable new invasive uses
    • Regulations and oversight consistently lag behind deployment

    Organizations Fighting for Your Privacy

    These groups and individuals are leading the fight against mass surveillance. Consider supporting their work or getting involved locally.

    Electronic Frontier Foundation (EFF)

    Leading nonprofit defending digital privacy and civil liberties. eff.org

    ACLU

    Fighting surveillance overreach through litigation and advocacy nationwide. aclu.org

    Fight for the Future

    Digital rights organization mobilizing grassroots opposition to surveillance. fightforthefuture.org

    Surveillance Technology Oversight Project (STOP)

    Litigating against invasive surveillance in New York and beyond. stopspying.org

    Institute for Justice

    This civil liberties law firm has filed lawsuits challenging the constitutionality of Flock's mass, warrantless surveillance ij.org

    Local Community Groups

    Check for privacy advocacy organizations in your area fighting surveillance at the local level.

    U.N. Human Rights Watchdogs Blast Columbia for Using Immigration Status to Suppress Students’ Pro-Palestine Speech

    Intercept
    theintercept.com
    2025-12-16 16:44:01
    The U.N. experts wrote blistering letters to five American universities about their crackdowns on Gaza protests. The post U.N. Human Rights Watchdogs Blast Columbia for Using Immigration Status to Suppress Students’ Pro-Palestine Speech appeared first on The Intercept....
    Original Article

    A commission of top United Nations human rights watchdogs sent a series of blistering letters to the heads of five U.S. universities raising sharp concerns over the treatment of pro-Palestine students, The Intercept has learned.

    The letters, which were sent on October 14 to the presidents and provosts of Columbia , Cornell , Georgetown , Minnesota State, and Tufts universities, called out school officials and U.S. law enforcement agencies for cracking down on student protesters and subsequently using immigration authorities to single out foreign students for detention and deportation.

    “We are highly concerned over reports that students were arrested, suspended, and expelled, and lost their university accommodation, campus access, and their immigration status merely because of assembling peacefully to express their solidarity with victims of the conflict in Gaza,” wrote the group of U.N. special rapporteurs, independent experts who monitor human rights violations. “We fear that such pressure and public attacks on scholars and institutions can result in repression of free expression and in self-censorship, thus damaging academic freedom and the autonomy of universities.”

    The letters suggest the international body has taken notice of domestic protest repression on U.S. campuses. Since President Donald Trump returned to office, his administration has weaponized immigration authorities against international students and investigations over alleged antisemitism at universities across the country — ratcheting up a crackdown on student protests for Palestine that began under former President Joe Biden.

    The letter to Columbia highlighted the arrest and detention of Mahmoud Khalil , Mohsen Mahdawi , and Leqaa Kordia , as well as the attempted arrest of Yunseo Chung . (Columbia did not immediately respond to a request for comment.)

    Khalil and Mahdawi both spent months in detention earlier this year. Kordia, a Palestinian student who was arrested on March 8, was still in U.S. Immigration and Customs Enforcement custody as recently as December 8, according to a report by Drop Site News .

    “It has been reported that the conditions of Ms. Kordia’s detention are particularly severe. Due to overcrowding, she sleeps on the floor where cockroaches and other bugs abound, and many showers and sinks do not work,” the authors wrote. “She is also not given materials her faith requires to have to pray, and she is not allowed to wear a hijab in the presence of men as her religion requires.”

    The authors of the letter include Mary Lawlor, the special rapporteur on the situation of human rights defenders; Farida Shaheed, the special rapporteur on the right to education; Irene Khan, the special rapporteur on the promotion and protection of the right to freedom of opinion and expression; Gina Romero, the special rapporteur on the rights to freedom of peaceful assembly and of association; and Gehad Madi, the special rapporteur on the human rights of migrants. Representatives of the U.N. rapporteurs who drafted the letters did not immediately respond to The Intercept’s requests for comment.

    The U.N. letter also highlighted the cases of Rümeysa Öztürk , a Turkish student at Tufts who was snatched by masked ICE agents on the streets of Somerville, Massachusetts, on March 25; Badar Khan Suri , the Indian-born researcher at Georgetown arrested on March 17; Momodou Taal , a Cornell grad student with dual citizenship from the United Kingdom and Gambia who was ordered to turn himself in to ICE agents on March 22; and Mohammed Hoque , a Minnesota State student arrested at his home on March 28. (Cornell, Minnesota State, and Tufts did not immediately respond to requests for comment.)

    In the letter, the authors singled out Columbia for bowing to pressure from the Trump administration, which they said set a standard that chilled speech nationwide.

    “The restrictive measures at Columbia University reflect nationwide structural changes at universities to suppress Palestine solidarity movements,” the authors wrote.

    In each letter, the authors asked the universities to provide information on the allegations of mistreatment, any measures taken by the schools to protect the rights of its students and scholars, and details on how the schools plan to safeguard the rights to freedom of expression and assembly.

    “Students report self-censoring political expression, and particularly international students are withdrawing from activism due to deportation fears,” the authors wrote. “Campus organizing has diminished significantly, with activists reporting less attendance from international students who had to quit their activism because of the potential risk of repercussions. This intimidating effect extends beyond issues concerning Israel and Palestine, with students reporting reluctance to engage in any political activism.”

    File d'attente - file-based job queue tool

    Lobsters
    git.sr.ht
    2025-12-16 16:36:13
    Comments...
    Original Article

    File d'attente (queue in French) is a file-based job queue, written in Go.

    File d'attente uses files and directories for queue manipulation. Create a job with " printf cmd > /pending/$id ", view running jobs with " ls /active ", and restart a failed job with " mv /failed/$id /pending ".

    The tool is intended for trusted, single-server workloads, as a companion queue to another application. File d'attente comes with automatic retries, timeout, and backoff built-in.

    # Installation

    File d'attente is built in Go and depends on sqlite and fuse (make sure fusermount is available in path).

    $ git clone https://sr.ht/~marcc/filed/
    $ cd filed
    $ go build
    $ go install
    

    To build the docs you need scdoc

    $ scdoc < filed.1.scd > filed.1
    # mv filed.1 /usr/local/man/man1
    

    # Getting started

    It is recommended to read the man pages for more complete documentation and security considerations, but below is a small example to get you started.

    filed requires a job directory and a state file location (defaulting to XDG_DATA_HOME ). Afterward, you can start the daemon:

    $ mkdir /tmp/filed-jobs
    $ filed /tmp/filed-jobs
    

    filed mounts the directory filed-jobs and exposes a few files and directories.

    A job can then be added by creating a file in the newly available pending directory:

    $ printf "echo 'hello world'" > /tmp/filed-jobs/pending/1
    

    If all went well, you can see the job output in /complete :

    $ cat /tmp/filed-jobs/complete/1
    >>> echo 'hello world'
    hello world
    

    By default, a job retries 3 times, and if unsuccessful, gets moved to /failed . You can inspect the logs to see what went wrong:

    $ printf "ech this-will-fail" > /tmp/filed-jobs/pending/2
    # Wait for a bit until it finishes retrying
    $ cat /tmp/filed-jobs/failed/2
    >>> ech this-will-fail
    sh: 1: ech: not found
    
    
    [System Error]: exit status 127
    

    You can restart a job by moving the job back to pending:

    $ mv /tmp/filed-jobs/failed/2 /tmp/filed-jobs/pending
    

    Finally, if you want to remove a completed or failed jobs:

    $ rm /tmp/filed-jobs/failed/2
    

    # Design & Motivation

    I wanted to create a queue that would be easy to use for self-hosted web applications, that could be used by any programming language. I also wanted to make it easy for admins to understand why a job fails, and to rerun jobs if there is an error.

    I was inspired by 9p, and files proved to be a great abstraction since directories model state transitions quite well. File d'attente makes it very easy to inspect the state, without needing to build an admin portal with separate sign in. Instead, all admin operations can be done by just SSHing into the server, and the operations for manipulating, securing and automating the system become very intuitive. The source code can then be very slimmed down, while still packing a lot of features.

    # TODO

    • [x] Support chmod and chown
    • [x] State is configured via environment variable
    • [x] Customizable backoff and timeout before retries
    • [x] Last modified and created at are correctly rendered for jobs
    • [ ] "Landlock"-mode, or sandboxed jobs - Requires a design
    • [ ] A reusable systemd unit file
    • [ ] A reusable openrc unit file
    • [ ] Notification on failure. Unfortunately inotify does not work with fuse , which would have been elegant otherwise.
    • [ ] Notify forget and other updates.

    # Status

    File d'attente is tested, but not battle-tested. There are probably quite a few warts and inefficiencies.

    # Alternatives

    • nq - nq is simpler and not a persistent process, but does not feature retries. They serve different purposes: nq for ad-hoc queuing of command lines. filed serves well as a job manager for your server, where you want admins to see jobs and be able to rerun them.
    • task-spooler - ts has better control over how you want the task executed (GPU or CPU), and a lot of other features. It does (AFAIK) not support retries, which are supported in filed .
    • bull - bull is only for node and javascript. It features a graphical UI, and a few other features not found in filed . filed eschews a GUI in favor of simple files, allowing it to better interoperate with other systems, and allows it to use regular unix permissions for access management.
    • sqs - requires you to setup most infrastructure around retries yourself. sqs is far more complex, more focused on message passing, harder to inspect, but far more flexible. Sqs scales better and fits more workloads.

    Show HN: Zenflow – orchestrate coding agents without "you're right" loops

    Hacker News
    zencoder.ai
    2025-12-16 16:32:16
    Comments...
    Original Article

    zenflow-parallel-agents-2

    ORCHESTRATION

    Parallel Project Execution

    Built-in verification means no waiting. Start the next task while agents finish the current one. Scale from one agent to your entire fleet.

    zenflow-kanbans

    VISIBILITY

    AI-First Project Management

    Projects, tasks, subtasks, kanban views, and inbox make AI work visible and organized. Clear picture across all your agents.

    zenflow-subtasks-1

    AUTOMATION

    Auto-Generated implementation plan

    Workflows break into sequential tasks automatically. Ready for autopilot or human review. Less babysitting, more producing.

    zenflow-models

    RELIABILITY

    Agent Diversity ??

    Different model families (Claude, GPT, etc.) challenge each other's assumptions and catch blind spots. Reduces errors, increases correctness.

    WHO IT'S FOR

    Built for AI-First Coders

    Senior Engineer

    Senior Engineers

    You own the architecture. Agents handle the implementation.

    Vibecoders

    Technical Vibecoders

    PMs, designers, and builders who think in outcomes, not syntax.

    Forward-looking team

    Forward-Looking Teams

    Standardize AI workflows. Guarantee quality. Ship faster, safer.

    WHAT TEAMS SAY

    From Hit-or-Miss to Production-Grade

    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris."

    Author photo

    Sarah Chen

    Engineering Lead

    "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident."

    Author photo

    Marcus Johnson

    Senior Developer

    "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."

    Author photo

    Alex Rivera

    CTO

    "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione."

    Author photo

    Jordan Kim

    Tech Lead

    gh-actions-lockfile: generate and verify lockfiles for GitHub Actions

    Lobsters
    gh-actions-lockfile.net
    2025-12-16 16:31:01
    Comments...
    Original Article

    Generate and verify lockfiles for GitHub Actions dependencies.
    Pin all actions to exact commit SHAs with integrity hashes.

    The Problem

    GitHub Actions has no built-in mechanism to lock dependency versions.

    Version tags like @v4 can be silently retagged to point to different code.

    Composite actions pull in transitive dependencies you can't see or audit.

    The Solution

    gh-actions-lockfile creates a lockfile that pins every action (including transitive dependencies) to exact commit SHAs with integrity hashes.

    Quick Start

    As a GitHub Action (recommended)

    Features

    • Pins actions to exact commit SHAs
    • Includes integrity hashes for verification
    • Resolves transitive dependencies from composite actions
    • Visualizes your action dependency tree
    • Runs as a GitHub Action or CLI tool
    • Zero runtime dependencies beyond Node.js

    Secure your workflows today

    gh-actions-lockfile is open source under the AGPL-3.0 license.

    The Future of [JetBrains] Fleet

    Lobsters
    blog.jetbrains.com
    2025-12-16 16:26:17
    Comments...
    Original Article
    Fleet logo

    More Than a Code Editor

    General News

    The Future of Fleet

    Ekaterina Prigara Aleksey Stukalov

    TL;DR

    Fleet started as our attempt to explore a new generation of JetBrains IDEs, developed in parallel with those based on the IntelliJ Platform. Over time, we learned that having two general-purpose IDE families created confusion and diluted our focus. Rebuilding the full capabilities of IntelliJ-based IDEs inside Fleet did not create enough value, and positioning Fleet as yet another editor did not justify maintaining two overlapping product lines.

    Starting December 22, 2025, Fleet will no longer be available for download. We are now building a new product focused on agentic development.

    Fleet vs. IntelliJ-based IDEs

    For many years, JetBrains focused on IntelliJ-based IDEs, which served as the primary environment for most developers. When we started Fleet, our goal was to explore a lighter architecture, a modern UI model, and a more flexible environment free from decades of legacy architectural decisions. It was a worthwhile experiment, and from both a technical and design perspective, it was a success. Many Fleet components now power JetBrains IDEs, and several UX and UI concepts have been adopted throughout our product lineup.

    However, Fleet did not succeed as a standalone product. We could neither replace IntelliJ IDEA with Fleet nor narrow it into a clear, differentiated niche. We suddenly had two IDE families aimed at largely the same audience, with overlapping purposes. Users kept asking which one to choose, and the answer was never short or satisfying. Two similar products created friction and raised questions about ownership and long-term investment.

    What we tried with Fleet

    We initially positioned Fleet as a lightweight multi-language IDE and then as an editor with smart coding assistance. For some time, we seriously considered whether Fleet could become a second flagship IDE family alongside IntelliJ-based tools. User feedback was consistent: If you already work with IntelliJ IDEA, Rider, WebStorm, PyCharm, or any other JetBrains IDE, switching to Fleet required a strong reason – and Fleet did not offer enough value to justify the transition from IDEs you already know and love.

    When AI matured, we explored Fleet as an AI-first editor. We built new workflows and conducted large-scale user research to understand potential differentiation and long-term value. We confirmed that another AI editor would not stand out, especially in a market filled with AI-first VS Code forks. It became increasingly clear that the best path forward was to strengthen AI workflows in our existing IDEs. However, rapid progress in AI revealed a different niche where Fleet fits much more naturally.

    What this new niche looks like

    While we worked on AI within the editor, a new development workflow began to take shape. Developers started delegating meaningful tasks to agents – updating tests, cleaning code, refactoring modules, exploring unfamiliar code paths, and even building new features. These tasks run asynchronously and return full patches. The developer doesn’t write the code themselves. They guide the agent and review its output. This is fundamentally different from the classic IDE workflow, which is based on immediate feedback, synchronous control, and a single stable local state.

    The agentic loop relies on structured task definition, context assembly, multiple asynchronous runs, isolated execution, and review-first workflows. Combining them in a single tool results in a disjointed experience, so the Fleet team chose to stop competing with IDEs and code editors and instead build a product focused on agentic workflows. This led to a pivot to a new product: an agentic development environment. Based on the Fleet platform, this new environment will ship as a new product with a new name. The technology, team, and long-term direction continue – but the product identity and the target market evolve.

    What changes for current Fleet users

    We will stop releasing any further updates for Fleet. Distribution will also end, so you will no longer be able to download Fleet from the Toolbox App or other channels starting December 22, 2025 .

    If you have already downloaded Fleet, you can continue using it. However, some features that rely on our server-side services, including AI Assistant, may stop working over time.

    We will continue to share updates about the new product as the work progresses. Stay tuned!

    Discover more

    Odin's Most Misunderstood Feature: `context` - gingerBill

    Lobsters
    www.gingerbill.org
    2025-12-16 16:14:06
    Comments...
    Original Article

    2025-12-15

    Even with the documentation on the topic, many people completely misunderstand what the context system is for, and what problem it actually solves.

    For those not familiar with Odin, in each scope, there is an implicit value named context . This context variable is local to each scope and is implicitly passed by pointer to any procedure call in that scope (if the procedure has the Odin calling convention).

    The main purpose of the implicit context system is for the ability to intercept third-party code and libraries and modify their functionality. One such case is modifying how a library allocates something or logs something. In C, this was usually achieved with the library defining macros which could be overridden so that the user could define what they wanted. However, not many libraries support this, in any language, by default which meant intercepting third-party code to see what it does and to change how it does it is generally not possible.

    The context value has default values for its parameters which is decided in the package runtime. These defaults are compiler specific. To see what the implicit context value contains, please see the definition of the Context struct in package runtime .

    The Misunderstanding

    Fundamentally, the entire point of the context system is to intercept third-party code, and to change how it does things. By third-party, I just mean code not written by yourself or code that you cannot easily modify (which could even be your own past self’s code).

    I expect most people to 100% ignore the context because its existence is not for whatever preconceived reason they think it is for, be that minimizing typing/passing things around, or dynamic scoping, etc. It’s just for interception of third-party code.

    Ironically, context works because people misunderstand it, and thus generally leave it alone. That allows those who do understand it to work around less-than-ideal API’s.

    I understand a lot of people may not understand why it exists when they might not currently need it, but it’s fundamentally a solution to a specific problem which cannot really be solved in another way.

    A common misunderstanding usually arises when it is necessary to interact with third-party code and having to write callbacks which do not use the Odin calling convention. There is a general misunderstanding that because some procedure may not appear to use context directly (or at least not obviously do so), people will say that they should be marked as "contextless" or "c" , however this misses the entire point. Because the default calling convention of Odin has this context , you don’t actually know if the code needs it or not (which is by design).

    The first common example of this of this interaction complain usually happens when using Odin’s printing procedures in core:fmt . For most people, they just do context = runtime.default_context() to define a context and then continue, but I have had a lot of people “complain” as to why that is even necessary. Arguing that other than the assert , why would you need the context ? This complaint is due to not understanding what fmt.printf et al actually do. printf is a wrapper around wprintf which takes in a generic io.Stream . Since other libraries can utilize these procedures, it might be necessary to intercept/override/track this behaviour. And from that, there is little choice to but require the context .

    A good APIs offers a way to specify the allocator to use, e.g. allocator: runtime.Allocator or allocator := context.allocator . An API that doesn’t offer it can be worked around by overriding the context.allocator for that call or series of calls, in the knowledge that the other programmer didn’t hardcode the allocator they gave to make , et al.

    What is Provided by the context ?

    The Allocators

    There are two allocators on the context.allocator and context.temp_allocator . I expect most people to never use custom allocators whatsoever (which is empirically true), but I do also want to encourage things like using the context.temp_allocator because it allows for many useful benefits, especially those that most people don’t even realize are a thing. For many people, they usually just want to do nothing with the context (assuming they know about it) or set the context.allocator to the mem.Tracking_Allocator and be done; that’s pretty much it.

    You could argue that it is “better” to pass allocators 1 around explicitly, but from my own experience in C with this exact interface (made and used well before I even made Odin), I found that I got in a very very lazy habit of not actually passing around allocators properly. This overly explicitness with a generalized interface lead to more allocation bugs than if I had used specific allocators on a per-system basis.

    When explicit allocators are wanted, you rarely want the generic interface too, and usually a specific allocator instead e.g. virtual.Arena . As I have previously expressed in my Memory Allocation Strategies series, an allocator can be used to represent a specific set of lifetimes for a set of allocations—arenas being the most common kind but other allocators such as pools, basic free lists, etc may be useful.

    However because most people will still default to a traditional malloc / free style of dynamic memory allocation, having a generic interface which can be overridden/intercepted/tracked is extremely useful to be able to do, especially in third-party libraries/code.

    n.b. Odin’s context.allocator defaults to a heap-like allocator on most platforms, and context.temp_allocator defaults to a growing arena-like allocator.

    assertion_failure_proc

    The field assertion_failure_proc exists because you might honestly want a different way of asserting, with more information it like stack traces. You might even want to use it as a mechanism to do a rudimentary sort of exception handling (similar to Go’s panic & recover ). Having this overridable is extremely useful, again with third-party code. I understand it does default to something when it is not set, but that’s still kind of the point still. It does need to assert/panic, which means it cannot just do nothing.

    logger

    Logging is common throughout most applications and we wanted to provide a default approach. I expect most people to default to this as they want a simple unified logging experience. Most people don’t want their logs to be handled by different libraries in numerous different ways BY DEFAULT . But because it is on the context , the default logging behaviour can now overridden easily. If you something more than this logger interface, then use what you want. The point as I keep trying to iterate is: what is the default and what will third-party libraries default to so that you can then intercept it if necessary?

    random_generator

    This is the newest addition to the context ; part of the reason for this being here is probably less than obvious. Sometimes a third-party library will do (pseudo-)random number generation but controlling how it does that is very hard (if not impossible).

    Take C’s rand() for example. If you know the library is using rand() , you can at least set a seed with srand() if you want a deterministic controlled output. However I have used libraries in C which use a different random number generator (thank goodness because rand() is dreadful), but I had no way to overriding it without modifying the source code directly (which is not always possible if it’s a precompiled LIB/DLL). The counter is when you want a cryptographic grade random number generator and you want non-determinacy whatsoever.

    Having a random generator be on the context allows for all of this kind of interception.

    n.b. Odin’s default random_generator is based on ChaCha8 is heavily optimized with SIMD.

    user_ptr and user_index

    If you have used C, you’ve probably experienced having callbacks where there is way to pass a custom user data pointer as part of it. The API designer has assumed that the callback is “pure”. However in reality, this is rarely the case, so how do you actually pass a callback (which is immediately used, not delayed) that you can pass user data too? The most obvious example of this is qsort , and even in the “pure” case, it is common to do a sort of a key based on an external table.

    There are two approaches that some people do in languages without closures (e.g. C and Odin) to get around these issues, but neither of which are great: global variables and/or thread local variables. Honestly, those are just dreadful solutions to the problem, and why context has the user_ptr and user_index fields, to allow you to intercept this poorly thought out API.

    Now you might be asking: Why both a pointer and an index? Why not just a pointer?

    From my experience of programming over many years, it is very common I just want to pass the same value to many callbacks but I want to access a different “element” inside of the data passed. Instead of creating a wrapper struct which has both this pointer and the index, I wanted to solve it by just having both already. It’s an empirically derived solution, not anything from “first principles”.

    I do recommend that an API should be designed to minimize the need for callbacks in the first place, but when necessary to at least have a user_ptr parameter for callbacks. For when people do not design good APIs, context is there to get around the crap.

    Lastly, _internal

    This just exists for internal use within the core library, which no-one should never use for any reason . Most of the time, it exists just for temporary things which will be improved in the future, or for passing things down the stack in a bodgy way. Again, this is not for the programmer, it’s for the compiler/core library developers only.

    Circumventing Bad APIs

    As I said in the user_ptr and user_index section, a lot of the impetus for making context comes from the experience of using numerous C libraries. The GOOD C libraries that allow for a form of interception usually do it through a macro; at best, they only do MY_MALLOC and MY_FREE style things, and sometimes MY_ASSERT . However, those are not the norm and usually only written by people in a similar “sphere of influence” to myself. Sadly, the average C library doesn’t allow for this.

    Even so, with the GOOD C libraries, this macro approach fails across a LIB/DLL boundary. Which is part of the problem when interfacing with a foreign language (e.g. Odin). So even in the GOOD case for C, it’s not that good in practice.

    Now some library writers are REALLY GOOD and they provide things like an allocation interface, but I probably know all of these library writers personally at this point, so I’d be preaching to the choir with my complaints.

    I’ve honestly had a few people effectively tell me that if it’s an bad API then the user should put up with it—“It’s API is bad? Oh well, tough luck”. However, I’ve had a lot the same people then ask “but why does the language need to solve that? Isn’t it a library problem?”.

    I’m sorry but telling someone the API is at fault doesn’t help them in the slightest, and if a API/library cannot be easily modified, then how can that be fixed in code? It’s fundamentally only fixable at the language itself.

    The Evolution of Code

    People rarely write things perfect the first time—code evolves. That’s what engineering is all about. Requirements change. The people change. The problem changes entirely. Expecting not to be able to intercept third-party code is pie-in-the-sky thinking. As I’ve said numerous times before, Third-party just means “stuff not written by you”; that’s it. As I stress, it could even be your past self, which is not the same as your present self.

    Point out that shitty APIs exist is the entire point. Just saying “tough luck” doesn’t solve anything, you’re adding to the problem.

    This is why context exists.

    ABI Layout

    One important aspect about the context is that memory layout is not user modifiable, and this is another big design choice too. It allows for a consistent and well understood ABI, which means you can—you guessed it—intercept third-party code even across LIB/DLL boundaries.

    If the user was allowed to add as many custom fields to the context as desired, it would not be ABI consistent, and thus not be stable for the use of its interception abilities across LIB/DLL boundaries. At best, allowing for custom fields is allowing you to minimize passing/typing parameters to procedures. Typing is rarely—if ever—the bottleneck in programming.

    Implementation

    Another common question I’ve gotten a few times is why the context is passed as an implicit pointer argument to a procedure, and not something like a thread local variable stack? The rationale being that there would not need to be a calling convention difference for context . Unfortunately through a lot of experimentation and thought, there are a few reasons why it is implemented the way it is:

    • Easier to manage across LIB/DLL boundaries that trying to use a single thread-local stack
    • Easier management of recovery from crashes where the context might be hard to figure out.
    • Using the existing stack makes stack management easier already, you don’t need to have a separate allocator for that stack
    • Some platforms do not thread-local variables (e.g. freestanding targets)
    • Works better with async/fiber based things, which would then require a fiber-local stack instead of a thread-local one
    • Prevent back-propagation, which would be trivial with a global/thread-local stack

    Odin’s context also has copy-on-write semantics. This is done for two reasons: to keep things local, and prevent back-propagation of “bad” data from an third-party library (be it malicious or just buggy). So not having an easily accessible stack of context values makes it harder for this back-propagation to happen.

    The Inspiration

    The main inspiration for the implicit context system does come from Jonathan Blow’s language, however I believe the reasoning for its existence in Jonathan Blow’s language is very different. As I have never used Jon’s language, I am only going on what other people have told me and what I have seen from Jon’s initial streams. From what I can tell, Jon’s language’s context behaves quite different to Odin’s, since it allows for the ability to add custom fields to it and to back-propagate.

    I am not sure what Jon’s initial rationale was for his form of context , but I do not believe Jon was thinking of third-party code interception when he designed/implemented his context . I hypothesize it was something closer to a form of “static dynamic-scoping” but not exactly (I know that’s an oxymoron of a statement). All I know is when I saw it, I saw a brilliant solution to third-party code interception problem.

    Conclusion

    I hope this clarifies a lot of the design rationale behind the implicit context system, and why it exists.

    If you have any more questions, or want me to clarify something further, please feel to contact me!

    Devs say Apple still flouting EU's Digital Markets Act six months on

    Hacker News
    www.theregister.com
    2025-12-16 16:09:48
    Comments...
    Original Article

    Six months after EU regulators found Apple's App Store rules in breach of the Digital Markets Act (DMA), developers say Cupertino is still behaving as if compliance were optional.

    The Coalition for App Fairness, a nonprofit organization of app developers and consumer groups, has accused Apple of persistent non-compliance with the DMA, warning that the company's revised App Store terms continue to impose fees which the legislation prohibits.

    In an open letter addressed to European Commission President Ursula von der Leyen and senior commissioners, the coalition argues that Apple has failed to deliver "any meaningful changes or proposals" despite an April 2025 non-compliance decision that found its App Store policies illegal and harmful to both developers and consumers.

    At the heart of the complaint is money. The DMA requires so-called gatekeepers to allow developers to offer and conduct transactions outside their app stores without charge. Apple, the coalition claims, is seeking to charge commissions of up to 20 percent on those very transactions.

    "This is a blatant disregard for the law with the potential to vanquish years of meaningful work by the Commission," the letter states, accusing Apple of preserving the economics of its App Store while nominally claiming compliance.

    Apple has said it will roll out new App Store terms in January 2026, but developers say the company has provided no clarity on what those changes will involve or whether they will actually comply with the DMA.

    "We have seen this playbook before in Europe and beyond," the signatories warn, adding that they suspect any new terms will continue to impose fees that would violate the law.

    The letter argues that this uncertainty is already doing damage. Six months after Apple's last App Store terms update, developers still do not know which rules will govern their businesses or what their costs will look like in the near term.

    Apple's "lack of transparency in tandem with its rushed timelines," the coalition says, is freezing investment and innovation, effectively allowing the company to "exploit its gatekeeper position by holding the entire industry hostage."

    The group also points to a growing transatlantic contrast that makes Europe look like the tougher regulator with the weaker results. While Apple continues to fight DMA enforcement in the EU, US courts have moved to curb its ability to extract fees from external transactions. Following litigation brought by Epic Games, developers in the US can now communicate freely with customers about pricing and offer payment options outside Apple's ecosystem without paying commission.

    That raises what the coalition calls a "simple and urgent question." Why should European developers and consumers get a worse deal than their US counterparts, especially when the EU was first to pass a landmark law aimed at fixing digital markets? The letter argues that meaningful enforcement of the DMA would strengthen Europe's digital competitiveness and attract global investment, while weak enforcement risks turning the regulation into an expensive paper exercise.

    "We trust the Commission will uphold the DMA," the signatories conclude, but they warn that if enforcement falls short, they will continue pressing policymakers to ensure Apple finally complies with the law as written – not as rewritten by Cupertino. ®

    Maybe consider putting cutlass in your CUDA/Triton kernels

    Lobsters
    maknee.github.io
    2025-12-16 16:02:29
    Comments...
    Original Article

    Motivation

    So I was browsing Hacker News and came across this interesting post: Fp8 runs ~100 tflops faster when the kernel name has “cutlass” in it .

    This was from Triton tutorial where someone noticed that adding “cutlass” to their kernel name gave them an additional 100-150 TFLOPs. That’s a huge improvement just from… a name?

    Mentions 100 TFLOPs improvement (Image source: Github pull )

    Mentions 150 TFLOPs improvement by renaming triton kernels to add cutlass (Image source: Github pull )

    Well, I got a bit curious and wanted to why this happens.

    So… what exactly is this?

    Instead of writing your kernel like this:

    __global__ void add(float *sum, int n, float *x, float *y)
    {
      for (int i = 0; i < n; i++)
        sum[i] = x[i] + y[i];
    }
    

    You add “cutlass” to the name:

    __global__ void add_cutlass(float *sum, int n, float *x, float *y)
    {
      for (int i = 0; i < n; i++)
        sum[i] = x[i] + y[i];
    }
    

    and ptxas If you need some background on the CUDA compilation toolchain, refer to the section on nvidia toolchain background will perform an additional pass that can add performance to the generated code.

    The rest of this blog will show benchmarks, explain the optimizations, and discuss when to use this trick. But I also want to highlight something broader: if you’re working at the high level (CUDA, Triton, PyTorch), you’re still at the mercy of what the backend compilers decide to do. In this case, ptxas (a black box) is making optimization decisions based on your kernel’s name With the recent release of TileIIR , there’s still plenty of magic happening under the hood. tileiras is also a black box, so we could easily see a similar “cutlass” trick emerge there too .

    If you want to skip to TLDR of the optimization, click here

    A cutlass example

    Here’s an example graph showing cutlass benchmarks with and without this optimization (where baseline/cutlass_on enables the optimization and cutlass_off disables it):

    Throughput of various cutlass examples

    In particular, the CuTE sgemm2.cu example sees a 20% drop in performance without the cutlass optimization!

    Another thing immediately obvious is that this optimzation doesnt always increase performance.

    Benchmarks

    Below are sections you can expand to see various benchmarks running on an RTX 3090 and H100. Each result is aggregated from 5 benchmark runs.

    Benchmarks include 15+ projects, covering popular ones like PyTorch, Flash Attention 2/3, Cutlass, llama.cpp.

    Some highlights:

    • Running llama.cpp on RTX 3090 with gpt-oss-20b shows a 1%+ performance increase
    • Flash Attention 2 on RTX 3090/H100 without the optimization decreases performance by up to 1%
    • Triton on RTX 3090 generally shows no performance change from the optimization

    Note: baseline doesn’t change anything. cutlass_on enables the optimization and cutlass_off disables it (if the application uses cutlass , for example Flash Attention 3):

    Expand to see 3090 benchmarks
    GPU Benchmarks
    RTX 3090 (Ampere) bitsandbytes candle cutlass flash_attn2 flashinfer ggml liger llamacpp llmc mojo nccl pytorch sageattention sgemm sglang tilus tinygrad torchao triton unsloth vllm

    Expand to see H100 benchmarks
    GPU Benchmarks
    H100 (Hopper) bitsandbytes cutlass deepep deepgemm_tflops flash_attn2 flash_attn3 flashinfer

    So what has it changed?

    So, I’ve added a godbolt reference for people to see the difference. I’m using some parts of SGEMM_CUDA If you haven’t checked it out, it’s a great blog on optimizing cuda matmul kernels by Simon Boehm as reference.

    In the NVCC compliation pipeline, cuda goes to ptx then ptx goes to sass. Let’s check verify where this optimization is applied (is it applied at the ptx or sass code)?

    High level compilation overview for NVIDIA GPUs

    First let’s explore if the cuda to ptx has changed.

    There's no difference in the PTX! (Image source: Godbolt link )

    Only the name has changed. The PTX instructions are identical.

    So let’s now check the the sass Godbolt link :

    Clearly something has changed!

    Two common changes we can see are:

    The optimization now uses IMAD instead of HMMA to zero registers

    We can see that IMAD is used instead of HMMA for zeroing registers, which is neat! Instead of using tensor units, we can use the FP32 units to zero out the registers. Refer to H100 SM Diagram .

    Enable interleaving LDS and FFMA

    We can see that LDS interleaved instead of being stacked together This should be able to increase instruction level parallelism

    One thing that the disassembly doesn’t show is the register pressure. This optimization may increase register pressure:

    cuobjdump --dump-resource-usage baseline.cubin
    
      Resource usage:
       Common:
        GLOBAL:0
       Function sgemm_kernel_10:
        REG:188 STACK:0 SHARED:17408 LOCAL:0 CONSTANT[0]:564 TEXTURE:0 SURFACE:0 SAMPLER:0
    
    cuobjdump --dump-resource-usage cutlass.cubin
    
      Resource usage:
       Common:
        GLOBAL:0
       Function cutlass_sgemm_kernel_9:
        REG:214 STACK:0 SHARED:17408 LOCAL:0 CONSTANT[0]:564 TEXTURE:0 SURFACE:0 SAMPLER:0
    
    

    Register usage increased from 188 to 214 , a 13% increase in register usage. However, this isn’t always the case. I’ve seen other examples not affect register pressure and even decrease register pressure.

    Below is a table of the different instructions that have changed for this kernel:

    Mnemonic Baseline CUTLASS Δ
    IMAD.MOV.U32 0 37 +37
    HFMA2.MMA 5 0 -5
    LEA 15 2 -13
    IMAD.SHL.U32 0 10 +10
    CS2R 75 64 -11
    MOV 8 0 -8
    IMAD 0 8 +8
    ULDC.64 4 1 -3
    FFMA 787 801 +14

    So… what is it doing?

    So far, we’ve dug into specifics. The higher optimization seems to most likely do the following:

    • Instruction selection - use f32 units instead of tensor cores for zeroing Zeroing registers isn’t in the hot path, but it’s a simple to see example! registers But wait there’s more! I didn’t show it in this blog in detail, but you can see some IMADs replacing instructions
    • Instruction reordering - mix memory loads with math
    • Influence register pressure - may increase the number of registers used to achieve reodering
    When ptxas sees matrix operations (MAD/MMA):
    
      Instruction selection:
        HMMA,MOV -> IMAD 
    
      Instruction reordering:
        LDS spread across FMMA
    
      As a Side effect:
        May increase register pressure
    

    When should you apply this optimization?

    With kernel writing, it’s tricky to say when you absolutely should and shouldn’t use this optimization. The optimization seems to increase ILP at the cost of register pressure Won’t increase register pressure in some cases! . Always benchmark to ensure the performance is good I’ve seen the optimization not affect performance on some cards while affecting others significantly .

    How to apply this to triton

    import torch
    import triton
    import triton.language as tl
    
    def rename_kernel(proxy):
        return "cutlass_kernel"
    
    # will convert "my_kernel" -> cutlass_kernel
    @triton.jit(repr=rename_kernel)
    def my_kernel(M: tl.constexpr):
        pass
    
    # compile and extract ptx
    my_kernel[(1,)](M=32)
    dev = torch.cuda.current_device()
    kernel_cache = my_kernel.device_caches[dev][0]
    compiled = next(iter(kernel_cache.values()))
    ptx = compiled.asm["ptx"]
    
    # print the kernel name from PTX
    print('\n'.join(ptx.splitlines()[:20]))
    
    

    It will show

    //
    // Generated by LLVM NVPTX Back-End
    //
    
    .version 8.7
    .target sm_86
    .address_size 64
    
            // .globl       cutlass_kernel          // -- Begin function cutlass_kernel
                                            // @cutlass_kernel
    .visible .entry cutlass_kernel(
            .param .u64 .ptr .global .align 1 cutlass_kernel_param_0,
            .param .u64 .ptr .global .align 1 cutlass_kernel_param_1
    )
    

    How to apply this to ptxas

    A universal patch to ptxas (which most frameworks invoke) is to just replace cutlass in the binary with something else.

    Here’s how I do it:

    input_path  = "/usr/local/cuda/bin/ptxas"
    output_path = "ptxas_no_cutlass"
    
    with open(input_path, "rb") as f:
        blob = bytearray(f.read())
    
    # We expect exactly "cutlass" inside ptxas.
    target = b"cutlass"
    off = blob.find(target)
    assert off != -1, "ptxas did not contain the cutlass marker!"
    
    # Overwrite: c u t l a s s  →  ff ff ff ff ff ff ff, so that strstr("0xFF") since kernel names contains ascii
    for i in range(len(target)):
        blob[off + i] = 0xFF
    
    with open(output_path, "wb") as f:
        f.write(blob)
    
    print(f"patched '{target.decode()}' at offset {off:#x}")
    

    Resolving Public Statements

    In my opinion, there seems to be a lot of assumptions people are throwing out on the internet about this optimization. I want to clear some of that up.

    On the top of the hackernews post , it links to a response from a user about this optimization.

    This statement is incorrect; I have compiled many real world projects with this optimization on and off and they ran without failing (passing output asserts) on different cards.

    Also with a highly voted reddit comment

    This explanation is really hard to understand. I’m guessing that the user is stating this trick uses NaNs/zeroes to optimize the program. It doesn’t use that. In fact, it tries to optimizes how registers are zeroed.

    Previous mentions

    This was also mentioned before by grynet on the nvidia forums where he complained that the following kernel would generate different sass

    __global__ void mykernel(float *lhs, float *rhs, float *res, int M, int N, int K) {
       cutlass::gemm::GemmCoord problem_size(M,N,K);
       compute_gemm_with_cutlass(lhs, rhs, res, problem_size);
    }
    
    __global__ void mykernel(float *lhs, float *rhs, float *res, int M, int N, int K, cutlass::gemm::GemmCoord dummy) {
       cutlass::gemm::GemmCoord problem_size(M,N,K);
       compute_gemm_with_cutlass(lhs, rhs, res, problem_size);
    }
    

    and BAR.SYNC.DEFER_BLOCKING would be generated here instead of BAR.SYNC (due to cutlass being added as part ofthe function signature)

    Perhaps this was also a part of the optimization in previous versions of ptxas ?

    Takeaway

    So, adding “cutlass” to your kernel name can give you 100+ TFLOPs or -20% FLOPS.

    The issue is two fold: ptxas is a black box and sass is undocumented. It’s unlike other ecosystems. You can see the passes running through LLVM and x86/arm are documented.

    Well, with this optimization… it helps some kernels, hurts others or change not much at all. Completely depends on your architecture and your specific code. What flies on an H100 might tank on a 5090 or B200, and you have no way to know until you run it.

    So what do you do? Benchmark it. Change the ordering in triton/cuda, see if PTX changes, check the SASS output. That’s the only way to know what ptxas actually did.

    And this isn’t going away. tileiras (the new TileIIR compiler) is also a black box. We may expect similar surprises like this moving forward.

    Appendix

    High level compilation overview for NVIDIA GPUs

    NVIDIA’s toolchain works like this: CUDA code is compiled by nvcc into PTX , an intermediate representation. Then ptxas takes that PTX and turns it into SASS , the low-level instruction set the GPU runs ptxas and sass are both undocumented, so it may be a bit difficult to understand what’s going on .

    H100 SM Diagram

    Citation

    To cite this article:

    @article{zhu2025cutlass,
      title = {Maybe consider putting "cutlass" in your CUDA/Triton kernels},
      author = {Zhu, Henry},
      journal = {maknee.github.io},
      year = {2025},
      month = {December},
      url = "https://maknee.github.io/blog/2025/Maybe-Consider-Putting-Cutlass-In-Your-CUDA-Kernels/"
    }
    

    Republicans Are Splitting Over Israel. Will Democrats Take Advantage?

    Intercept
    theintercept.com
    2025-12-16 16:00:24
    A new poll shows a growing divide among Republicans, especially under 45, on U.S. support for Israel. Democrats have a chance to pick up their votes. The post Republicans Are Splitting Over Israel. Will Democrats Take Advantage? appeared first on The Intercept....
    Original Article

    In a presidential primary election, a significant number of Republican voters — 44 percent — said they would vote for a Republican candidate who supports reducing the flow of U.S. taxpayer-funded weapons to Israel, according to a new poll released Tuesday by the Institute for Middle East Understanding Policy Project and conducted by YouGov.

    The findings show it’s not just left-leaning voters who now object to Israel’s war on Gaza — a growing share of Republicans are souring on the U.S. government’s unconditional support of Israel as well. That creates an opportunity for Democrats who want to flip Republican seats in upcoming elections, said Margaret DeReus, executive director of the IMEU Policy Project.

    “Democratic leadership has so far refused to acknowledge Israel’s growing unpopularity with voters and offer voters a real alternative, the same disastrous mistake they made in 2024,” DeReus said. “If Democratic leadership can summon the political will to call for an end of weapons to Israel so those billions can be reinvested in the programs Americans need, our polling finds it won’t just boost support with the Democratic base — it will persuade Republican voters to cross over as well.”

    It depends in part on which Republicans a Democratic candidate wants to court. Similar to trends seen among Democratic voters about a decade ago, the Republican opposition contains a notable age gap: Among Republicans ages 18 to 44, the new IMEU poll said, support for a candidate who favors reducing arms transfers to Israel jumps to a majority, 51 percent.

    The poll was taken from a sample of 1,287 self-identified Republicans who YouGov surveyed online in November. With a 3 percent margin of error, the results are consistent with findings from an August Quinnipiac University poll that found more than a third of Republicans oppose sending more military aid to Israel, and an October Pew Research Center poll finding that as many 41 percent of Republicans have an unfavorable view of Israel , a jump from 27 percent only three years ago. A Gallup poll in July showed that a majority of all Americans — 54 percent — disapprove of Israel’s military actions in Gaza, a new high in dissatisfaction.

    As the 2026 congressional primaries draw near, the Democratic Party is continuing to grapple with how to respond to mounting pressure to support Palestine among its voter base. Some Democratic candidates have sworn off support from conservative pro-Israel groups such as the American Israel Public Affairs Committee after previously receiving funding , and are committing to a House bill that would block offensive weapons transfers to Israel; others remain committed to the pro-Israel cause.

    Asked if they would rather support a Republican or Democratic candidate running on identical pro-Israel messages — that Israel should “do whatever its leaders say is necessary to defend itself” and that “the United States should always be there to provide weapons and logistical support to Israel when its leaders ask” — only 4 percent of the polled Republicans said they would vote for the Democrat.

    But asked to pick between the pro-Israel Republican or a Democratic candidate whose priority is to “focus on Americans first, by ensuring our tax dollars are used to bring down prices here instead of paying for weapons and support for wealthy nations like Israel,” 17 percent of Republicans flipped left and said they would rather vote for a Democrat critical of Israel.

    DeReus interpreted the results as indicative of frustration with President Donald Trump.

    “Americans of all backgrounds are confounded that President Trump always finds billions of dollars to fund Israel’s attacks on Palestinians, while saying there’s not enough money to fund affordable healthcare for Americans,” she said.

    The IMEU poll also found that among Republican voters, more than a third said they would rather support a Republican primary congressional candidate who rejected money from AIPAC, compared to 19 percent support for a candidate who accepts AIPAC donations.

    When asked specifically about U.S.-funded weapons deals with Israel, Republican voters signaled significant disapproval. The arms transfers between the two countries operate within a Memorandum of Understanding signed in 2016 by then-President Barack Obama that expires in 2028. Last month, Axios reported that Israel is seeking a new 20-year MOU with the Trump administration, committing about $4 billion to Israel each year. The proposal reportedly asks for a reduction in the amount of money used for direct military aid with plans to instead spend such money on defense-related research, a possible concession to growing frustrations with Israel among Trump’s base, especially as the economy worsens.

    The IMEU poll confirms some of that frustration, showing that 42 percent of Republican voters want the current U.S.–Israel military MOU to lapse in 2028 rather than renewing another 10-year agreement. Disapproval for the 20-year agreement slightly increases to 43 percent. A majority of Republicans below the age of 44 opposed a 10- or 20-year agreement, at 53 percent and 51 percent, respectively.

    Amid Israel’s war on Gaza, former President Joe Biden approved a 2024 emergency bill sending $14.1 billion in military aid to Israel, in addition to the ongoing MOU. A new congressional defense bill released last week, which asks for a record $901 billion, also includes carveouts for the U.S. to fill any of Israel’s gaps in military aid created by arms embargoes by other nations, such as Spain , Italy, and Japan, according to a Zeteo report .

    Some on the left who support Palestinian human rights are beginning to capitalize on their overlap with conservatives — like Code Pink founder Medea Benjamin, who last week met with far-right Rep. Marjorie Taylor Greene, R-Ga., who is resigning in January and has been seen as an avatar for growing dissatisfaction toward U.S. support for Israel among Trump’s supporters.

    That’s not to say right-wing criticism of pro-Israel spending is necessarily born out of concern for Palestinian people . The strain of conservatism that gave rise to Greene and other “America first” Republicans relies on a nationalist logic that privileges U.S. citizens above all other people, and right-wing criticism of Israel often peddles in antisemitic tropes. The influential right-wing pundit Tucker Carlson has criticized U.S. support for Israel’s genocide in Gaza — and recently drew criticism for platforming Nick Fuentes, a white nationalist who often spews antisemitic beliefs.

    Brett Cooper, another popular conservative personality and regular Fox News contributor, attempted to untangle this concern in a recent interview on NPR. When host Steve Inskeep asked Cooper whether she agreed with Fuentes’s peddling of an antisemitic idea that the U.S. is run by “Jewish gangsters,” Cooper, 24, said she rejected Fuentes’s antisemitic claim and instead insisted her generation’s concern with Israel had more to do with spending priorities in a struggling U.S. economy.

    “Young people’s biggest concern right now, both sides of the aisle, is the economy — we are concerned about being able to buy homes, we are concerned about affordability,” Cooper said. “And so when we see the news, when we see how much money is being sent overseas, to Ukraine, to Israel … my generation is concerned, we are upset.”

    Hackers exploit newly patched Fortinet auth bypass flaws

    Bleeping Computer
    www.bleepingcomputer.com
    2025-12-16 15:57:34
    Hackers are exploiting critical-severity vulnerabilities affecting multiple Fortinet products to get unauthorized access to admin accounts and steal system configuration files. [...]...
    Original Article

    Hackers exploit newly patched Fortinet auth bypass flaws

    Hackers are exploiting critical-severity vulnerabilities affecting multiple Fortinet products to get unauthorized access to admin accounts and steal system configuration files.

    The two vulnerabilities are tracked as CVE-2025-59718 and CVE-2025-59719, and Fortinet warned in an advisory on December 9 about the potential for exploitation.

    CVE-2025-59718 is a FortiCloud SSO authentication bypass affecting FortiOS, FortiProxy, and FortiSwitchManager. It is caused by improper verification of cryptographic signatures in SAML messages, allowing an attacker to log in without valid authentication by submitting a maliciously crafted SAML assertion.

    CVE-2025-59719 is a FortiCloud SSO authentication bypass affecting FortiWeb. It arises from a similar issue with the cryptographic signature validation of SAML messages, enabling unauthenticated administrative access via forged SSO.

    Both issues are only exploitable if FortiCloud SSO is enabled, which is not the default setting. However, unless the feature is explicitly disabled, it is activated automatically when registering devices through the FortiCare user interface.

    Targeting admin accounts

    Researchers at cybersecurity company Arctic Wolf observed attacks exploiting the two security vulnerabilities starting on December 12. They note that the intrusions originated from several IP addresses linked to The Constant Company, BL Networks, and Kaopu Cloud HK.

    Based on Arctic Wolf observations, the attackers targeted admin accounts with malicious single sign-on logins (SSO), as seen in the log below:

    Log showing authentication bypass
    Log showing authentication bypass
    Source: Arctic Wolf

    After obtaining admin-level access, the hackers accessed the web management interface and performed actions such as downloading the system’s configuration files.

    Action logs
    Malicious actions log
    Source: Arctic Wolf

    Configuration files can expose network layouts, internet-facing services, firewall policies, potentially vulnerable interfaces, routing tables, and also hashed passwords that may be cracked if weak.

    The exfiltration of these files suggests that the activity is not from researchers mapping vulnerable endpoints, as exploitation is part of a malicious operation that may support future attacks.

    Blocking the attacks

    The two flaws impact multiple versions of Fortinet products except for FortiOS 6.4, FortiWeb 7.0, and FortiWeb 7.2.

    To prevent attacks, Fortinet recommends that admins still running a vulnerable version temporarily disable the FortiCloud login feature until an upgrade to a safer version is possible.

    This can be done from System → Settings → “Allow administrative login using FortiCloud SSO” = Off.

    System administrators are recommended to move to one of the following versions that address both vulnerabilities:

    • FortiOS 7.6.4+, 7.4.9+, 7.2.12+, and 7.0.18+
    • FortiProxy 7.6.4+, 7.4.11+, 7.2.15+, 7.0.22+
    • FortiSwitchManager 7.2.7+, 7.0.6+
    • FortiWeb 8.0.1+, 7.6.5+, 7.4.10+

    If any signs of compromise are discovered, it is recommended to rotate firewall credentials as soon as possible. Arctic Wolf also recommends limiting firewall/VPN management access to trusted internal networks only.

    tines

    Break down IAM silos like Bitpanda, KnowBe4, and PathAI

    Broken IAM isn't just an IT problem - the impact ripples across your whole business.

    This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

    AIsbom – open-source CLI to detect "Pickle Bombs" in PyTorch models

    Hacker News
    github.com
    2025-12-16 15:55:45
    Comments...
    Original Article

    AIsbom: The Supply Chain for Artificial Intelligence

    PyPI version License Python Compliance

    AIsbom is a specialized security and compliance scanner for Machine Learning artifacts.

    Unlike generic SBOM tools that only parse requirements.txt , AIsbom performs Deep Binary Introspection on model files ( .pt , .pkl , .safetensors ) to detect malware risks and legal license violations hidden inside the serialized weights.

    AIsbom Demo


    ⚡ Quick Start

    1. Installation

    Install directly from PyPI. No cloning required.

    Note: The package name is aisbom-cli, but the command you run is aisbom.

    2. Run a Scan

    Point it at any directory containing your ML project. It will find requirements files AND binary model artifacts.

    aisbom scan ./my-project-folder

    3. Output

    You will see a combined Security & Legal risk assessment in your terminal:

    🧠 AI Model Artifacts Found

    Filename Framework Security Risk Legal Risk
    bert_finetune.pt PyTorch 🔴 CRITICAL (RCE Detected: posix.system) UNKNOWN
    safe_model.safetensors SafeTensors 🟢 LOW (Binary Safe) UNKNOWN
    restricted_model.safetensors SafeTensors 🟢 LOW LEGAL RISK (cc-by-nc-4.0)

    A compliant sbom.json (CycloneDX v1.6) including SHA256 hashes and license data will be generated in your current directory.


    4. Visualize the Report (New!)

    Don't like reading JSON? You can visualize your security posture using our offline viewer.

    1. Run the scan.
    2. Go to aisbom.io/viewer.html .
    3. Drag and drop your sbom.json .
    4. Get an instant dashboard of risks, license issues, and compliance stats.

    Note: The viewer is client-side only. Your SBOM data never leaves your browser.


    🚀 Why AIsbom?

    AI models are not just text files; they are executable programs and IP assets.

    • The Security Risk: PyTorch ( .pt ) files are Zip archives containing Pickle bytecode. A malicious model can execute arbitrary code (RCE) instantly when loaded.
    • The Legal Risk: A developer might download a "Non-Commercial" model (CC-BY-NC) and deploy it to production. Since the license is hidden inside the binary header, standard tools miss it.
    • Pickle files can execute arbitrary code (RCE) instantly upon loading.
    • The Solution: Legacy scanners look at requirements.txt manifest files but ignore binary model weights. We look inside. We decompile the bytecode headers without loading the heavy weights into RAM.

    ✨ Key Features

    • 🧠 Deep Introspection: Peeks inside PyTorch Zip structures and Safetensors headers without loading weights into RAM.
    • 💣 Pickle Bomb Detector: Disassembles bytecode to detect os.system , subprocess , and eval calls before they run.
    • ⚖️ License Radar: Extracts metadata from .safetensors to flag restrictive licenses (e.g., CC-BY-NC, AGPL) that threaten commercial use.
    • 🛡️ Compliance Ready: Generates standard CycloneDX v1.6 JSON for enterprise integration (Dependency-Track, ServiceNow).
    • ⚡ Blazing Fast: Scans GB-sized models in milliseconds by reading headers only and using streaming hash calculation.

    🧪 How to Verify (The "Trust Factor")

    Security tools require trust. To maintain a safe repository, we do not distribute malicious binaries. However, AIsbom includes a built-in generator so you can create safe "test dummies" to verify the scanner works.

    1. Install:

    2. Generate Test Artifacts: Run this command to create a fake "Pickle Bomb" and a "Restricted License" model in your current folder.

    # Generate a mock Pickle Bomb (Security Risk) and a mock Non-Commercial Model (Legal Risk)
    aisbom generate-test-artifacts

    Result: Files named mock_malware.pt and mock_restricted.safetensors are created.

    3. Scan it:

    # You can use your globally installed aisbom, or poetry run aisbom
    aisbom scan .

    You will see the scanner flag mock_malware.pt as CRITICAL and mock_restricted.safetensors as a LEGAL RISK .


    🔒 Security Logic

    AIsbom uses a static analysis engine to disassemble Python Pickle opcodes. It looks for specific GLOBAL and STACK_GLOBAL instructions that reference dangerous modules:

    • os / posix (System calls)
    • subprocess (Shell execution)
    • builtins.eval / exec (Dynamic code execution)
    • socket (Network reverse shells)

    🤖 GitHub Actions Integration

    Add AIsbom to your CI/CD pipeline to block unsafe models before they merge.

    name: AI Security Scan
    on: [pull_request]
    
    jobs:
      aisbom-scan:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          
          - name: Scan AI Models
            uses: Lab700xOrg/aisbom@v0
            with:
              directory: '.'

    Biscuit is a specialized PostgreSQL index for fast pattern matching LIKE queries

    Lobsters
    github.com
    2025-12-16 15:39:37
    Comments...
    Original Article

    Biscuit - High-Performance Pattern Matching Index for PostgreSQL

    License: MIT PostgreSQL: 12+ Read the Docs

    Biscuit is a specialized PostgreSQL index access method (IAM) designed for blazing-fast pattern matching on LIKE and ILIKE queries, with native support for multi-column searches. It eliminates the recheck overhead of trigram indexes while delivering significant performance improvements on wildcard-heavy queries. It stands for Bitmap Indexed Searching with Comprehensive Union and Intersection Techniques .


    What's new?

    ✨ New Features

    Added Index Memory Introspection Utilities

    Added built-in SQL functions and a view to inspect Biscuit index in-memory footprint .

    • biscuit_index_memory_size(index_oid oid) → bigint Low-level C-backed function returning the exact memory usage (in bytes) of a Biscuit index currently resident in memory.

    • biscuit_index_memory_size(index_name text) → bigint Convenience SQL wrapper accepting an index name instead of an OID.

    • biscuit_size_pretty(index_name text) → text Human-readable formatter that reports Biscuit index memory usage in bytes, KB, MB, or GB while preserving the exact byte count.

    • biscuit_memory_usage view A consolidated view exposing:

      • schema name
      • table name
      • index name
      • Biscuit in-memory size
      • human-readable memory size
      • on-disk index size (via pg_relation_size )

      This allows direct comparison between in-memory Biscuit structures and their persistent disk representation .

    SELECT * FROM biscuit_memory_usage;

    Notes

    • Memory accounting reflects Biscuit’s deliberate cache persistence design, intended to optimize repeated pattern-matching workloads.
    • Functions are marked VOLATILE to ensure accurate reporting of live memory state.
    • pg_size_pretty(pg_relation_size(...)) reports only the on-disk footprint of the Biscuit index. Since Biscuit maintains its primary structures in memory (cache buffers / AM cache), the reported disk size may significantly underrepresent the index’s effective total footprint during execution. Hence, we recommend the usage of biscuit_size_pretty(...) to view the actual size of the index.

    ⚙️ Performance improvements

    Removed redundant bitmaps

    Separate bitmaps for length-based filtering for case-insensitive search were removed. Case insensitive searches now use the same length-based filtering bitmaps as case-sensitive ones.


    Installation

    Requirements

    • Build tools: gcc , make , pg_config
    • Optional: CRoaring library for enhanced performance

    From Source

    # Clone repository
    git clone https://github.com/Crystallinecore/biscuit.git
    cd biscuit
    
    # Build and install
    make
    sudo make install
    
    # Enable in PostgreSQL
    psql -d your_database -c "CREATE EXTENSION biscuit;"

    From PGXN

    pgxn install biscuit
    psql -d your_database -c "CREATE EXTENSION biscuit;"

    Quick Start

    Basic Usage

    -- Create a Biscuit index
    CREATE INDEX idx_users_name ON users USING biscuit(name);
    
    -- Query with wildcard patterns
    SELECT * FROM users WHERE name LIKE '%john%';
    SELECT * FROM users WHERE name NOT LIKE 'a%b%c';
    SELECT COUNT(*) FROM users WHERE name LIKE '%test%';

    Multi-Column Indexes

    -- Create multi-column index
    CREATE INDEX idx_products_search 
    ON products USING biscuit(name, description, category);
    
    -- Multi-column query (optimized automatically)
    SELECT * FROM products 
    WHERE name LIKE '%widget%' 
      AND description LIKE '%blue%'
      AND category LIKE 'electronics%'
    ORDER BY score DESC 
    LIMIT 10;

    Supported Data Types

    Biscuit automatically converts various types to searchable text:

    -- Text types (native)
    CREATE INDEX ON logs USING biscuit(message);
    
    -- Numeric types (converted to sortable strings)
    CREATE INDEX ON events USING biscuit(user_id, event_code);
    
    -- Date/Time types (converted to sortable timestamps)
    CREATE INDEX ON orders USING biscuit(order_date, customer_name);
    
    -- Boolean (converted to 't'/'f')
    CREATE INDEX ON flags USING biscuit(is_active, status);

    How It Works

    Core Concept: Bitmap Position Indices

    Biscuit builds two types of character-position bitmaps for every string:

    1. Positive Indices (Forward)

    Tracks which records have character c at position p :

    String: "Hello"
    Bitmaps:
      H@0 → {record_ids...}
      e@1 → {record_ids...}
      l@2 → {record_ids...}
      l@3 → {record_ids...}
      o@4 → {record_ids...}
    

    2. Negative Indices (Backward)

    Tracks which records have character c at position -p from the end:

    String: "Hello"
    Bitmaps:
      o@-1 → {record_ids...}  (last char)
      l@-2 → {record_ids...}  (second to last)
      l@-3 → {record_ids...}
      e@-4 → {record_ids...}
      H@-5 → {record_ids...}
    

    3. Positive Indices (Case-insensitive)

    Tracks which records have character c at position p :

    String: "Hello"
    Bitmaps:
      h@0 → {record_ids...}
      e@1 → {record_ids...}
      l@2 → {record_ids...}
      l@3 → {record_ids...}
      o@4 → {record_ids...}
    

    4. Negative Indices (Case-insensitive)

    Tracks which records have character c at position -p from the end:

    String: "Hello"
    Bitmaps:
      o@-1 → {record_ids...}  (last char)
      l@-2 → {record_ids...}  (second to last)
      l@-3 → {record_ids...}
      e@-4 → {record_ids...}
      h@-5 → {record_ids...}
    

    5. Length Bitmaps

    Two types for fast length filtering:

    • Exact length : length[5] → all 5-character strings
    • Minimum length : length_ge[3] → all strings ≥ 3 characters

    Pattern Matching Algorithm

    Example: LIKE '%abc%def'

    Step 1: Parse pattern into parts

    Parts: ["abc", "def"]
    Starts with %: YES
    Ends with %: NO
    

    Step 2: Match first part as prefix

    -- "abc" must start at position 0
    Candidates = pos[a@0] ∩ pos[b@1] ∩ pos[c@2]

    Step 3: Match last part at end (negative indexing)

    -- "def" must end at string end
    Candidates = Candidates ∩ neg[f@-1] ∩ neg[e@-2] ∩ neg[d@-3]

    Step 4: Apply length constraint

    -- String must be at least 6 chars (abc + def)
    Candidates = Candidates ∩ length_ge[6]

    Result: Exact matches, zero false positives


    Why It's Fast

    1. Pure Bitmap Operations

    // Traditional approach (pg_trgm)
    for each trigram in pattern:
        candidates = scan_trigram_index(trigram)
        for each candidate:
            if !heap_fetch_and_recheck(candidate):  // SLOW: Random I/O
                remove candidate
    
    // Biscuit approach
    for each character at position:
        candidates &= bitmap[char][pos]  // FAST: In-memory AND
    // No recheck needed!

    2. Roaring Bitmaps

    Compressed bitmap representation:

    • Sparse data: array of integers
    • Dense data: bitset
    • Automatic conversion for optimal memory

    3. Negative Indexing Optimization

    -- Pattern: '%xyz'
    -- Traditional: Scan all strings, check suffix
    -- Biscuit: Direct lookup in neg[z@-1] ∩ neg[y@-2] ∩ neg[x@-3]

    12 Performance Optimizations

    1. Skip Wildcard Intersections

    // Pattern: "a_c" (underscore = any char)
    // OLD: Intersect all 256 chars at position 1
    // NEW: Skip position 1 entirely, only check a@0 and c@2

    2. Early Termination on Empty

    result = bitmap[a][0];
    result &= bitmap[b][1];
    if (result.empty()) return empty;  // Don't process remaining chars

    3. Avoid Redundant Bitmap Copies

    // OLD: Copy bitmap for every operation
    // NEW: Operate in-place, copy only when branching

    4. Optimized Single-Part Patterns

    Fast paths for common cases:

    • Exact : 'abc' → Check position 0-2 and length = 3
    • Prefix : 'abc%' → Check position 0-2 and length ≥ 3
    • Suffix : '%xyz' → Check negative positions -3 to -1
    • Substring : '%abc%' → Check all positions, OR results

    5. Skip Unnecessary Length Operations

    // Pure wildcard patterns
    if (pattern == "%%%___%%")  // 3 underscores
        return length_ge[3];     // No character checks needed!

    6. TID Sorting for Sequential Heap Access

    // Sort TIDs by (block_number, offset) before returning
    // Converts random I/O into sequential I/O
    // Uses radix sort for >5000 TIDs, quicksort for smaller sets

    7. Batch TID Insertion

    // For bitmap scans, insert TIDs in chunks
    for (i = 0; i < num_results; i += 10000) {
        tbm_add_tuples(tbm, &tids[i], batch_size, false);
    }

    8. Direct Roaring Iteration

    // OLD: Convert bitmap to array, then iterate
    // NEW: Direct iterator, no intermediate allocation
    roaring_uint32_iterator_t *iter = roaring_create_iterator(bitmap);
    while (iter->has_value) {
        process(iter->current_value);
        roaring_advance_uint32_iterator(iter);
    }

    9. Batch Cleanup on Threshold

    // After 1000 deletes, clean tombstones from all bitmaps
    if (tombstone_count >= 1000) {
        for each bitmap:
            bitmap &= ~tombstones;  // Batch operation
        tombstones.clear();
    }

    10. Aggregate Query Detection

    // COUNT(*), EXISTS, etc. don't need sorted TIDs
    if (!scan->xs_want_itup) {
        skip_sorting = true;  // Save sorting time
    }

    11. LIMIT-Aware TID Collection

    // If LIMIT 10 in query, don't collect more than needed
    if (limit_hint > 0 && collected >= limit_hint)
        break;  // Early termination

    12. Multi-Column Query Optimization

    Predicate Reordering

    Analyzes each column's pattern and executes in order of selectivity:

    -- Query:
    WHERE name LIKE '%common%'           -- Low selectivity
      AND sku LIKE 'PROD-2024-%'         -- High selectivity (prefix)
      AND description LIKE '%rare_word%' -- Medium selectivity
    
    -- Execution order (Biscuit automatically reorders):
    1. sku LIKE 'PROD-2024-%'         (PREFIX, priority=20, selectivity=0.02)
    2. description LIKE '%rare_word%' (SUBSTRING, priority=35, selectivity=0.15)
    3. name LIKE '%common%'           (SUBSTRING, priority=55, selectivity=0.60)

    Selectivity scoring formula:

    score = 1.0 / (concrete_chars + 1)
          - (underscore_count × 0.05)
          + (partition_count × 0.15)
          - (anchor_strength / 200)
    

    Priority tiers:

    1. 0-10 : Exact matches, many underscores
    2. 10-20 : Non-% patterns with underscores
    3. 20-30 : Strong anchored patterns (prefix/suffix)
    4. 30-40 : Weak anchored patterns
    5. 40-50 : Multi-partition patterns
    6. 50-60 : Substring patterns (lowest priority)

    Benchmarking

    Setup Test Data

    -- Create 1M row test table
    CREATE TABLE benchmark (
        id SERIAL PRIMARY KEY,
        name TEXT,
        description TEXT,
        category TEXT,
        score FLOAT
    );
    
    INSERT INTO benchmark (name, description, category, score)
    SELECT 
        'Name_' || md5(random()::text),
        'Description_' || md5(random()::text),
        'Category_' || (random() * 100)::int,
        random() * 1000
    FROM generate_series(1, 1000000);
    
    -- Create indexes
    CREATE INDEX idx_trgm ON benchmark 
        USING gin(name gin_trgm_ops, description gin_trgm_ops);
    
    CREATE INDEX idx_biscuit ON benchmark 
        USING biscuit(name, description, category);
    
    ANALYZE benchmark;

    Run Benchmarks

    -- Single column, simple pattern
    EXPLAIN ANALYZE
    SELECT * FROM benchmark WHERE name LIKE '%abc%' LIMIT 100;
    
    -- Multi-column, complex pattern
    EXPLAIN ANALYZE
    SELECT * FROM benchmark 
    WHERE name LIKE '%a%b' 
      AND description LIKE '%bc%cd%'
    ORDER BY score DESC 
    LIMIT 10;
    
    -- Aggregate query (COUNT)
    EXPLAIN ANALYZE
    SELECT COUNT(*) FROM benchmark 
    WHERE name LIKE 'a%l%' 
      AND category LIKE 'f%d';
    
    -- Complex multi-part pattern
    EXPLAIN ANALYZE
    SELECT * FROM benchmark 
    WHERE description LIKE 'u%dc%x'
    LIMIT 50;

    View Index Statistics

    -- Show internal statistics
    SELECT biscuit_index_stats('idx_biscuit'::regclass);

    Output:

    ----------------------------------------------------
     Biscuit Index Statistics (FULLY OPTIMIZED)        +
     ==========================================        +
     Index: idx_biscuit                                +
     Active records: 1000002                           +
     Total slots: 1000002                              +
     Free slots: 0                                     +
     Tombstones: 0                                     +
     Max length: 44                                    +
     ------------------------                          +
     CRUD Statistics:                                  +
       Inserts: 0                                      +
       Updates: 0                                      +
       Deletes: 0                                      +
     ------------------------                          +
     Active Optimizations:                             +
       ✓ 1. Skip wildcard intersections                +
       ✓ 2. Early termination on empty                 +
       ✓ 3. Avoid redundant copies                     +
       ✓ 4. Optimized single-part patterns             +
       ✓ 5. Skip unnecessary length ops                +
       ✓ 6. TID sorting for sequential I/O             +
       ✓ 7. Batch TID insertion                        +
       ✓ 8. Direct bitmap iteration                    +
       ✓ 9. Parallel bitmap scan support               +
       ✓ 10. Batch cleanup on threshold                +
       ✓ 11. Skip sorting for bitmap scans (aggregates)+
       ✓ 12. LIMIT-aware TID collection                +
    

    Results

    Index Command Build Time
    pg_trgm CREATE INDEX idx_trgm ... 20,358.655 ms
    biscuit CREATE INDEX idx_biscuit ... 2,734.310 ms

    Use Cases

    1. Full-Text Search Applications

    -- E-commerce product search
    CREATE INDEX idx_products ON products 
        USING biscuit(name, brand, description);
    
    SELECT * FROM products 
    WHERE name LIKE '%laptop%' 
      AND brand LIKE 'ABC%'
      AND description LIKE '%gaming%'
    ORDER BY price DESC 
    LIMIT 20;

    2. Log Analysis

    -- Search error logs
    CREATE INDEX idx_logs ON logs 
        USING biscuit(message, source, level);
    
    SELECT * FROM logs 
    WHERE message LIKE '%ERROR%connection%timeout%'
      AND source LIKE 'api.%'
      AND timestamp > NOW() - INTERVAL '1 hour'
    LIMIT 100;

    3. Customer Support / CRM

    -- Search tickets by multiple fields
    CREATE INDEX idx_tickets ON tickets 
        USING biscuit(subject, description, customer_name);
    
    SELECT * FROM tickets 
    WHERE subject LIKE '%refund%'
      AND customer_name LIKE 'John%'
      AND status = 'open'
    ORDER BY created_at DESC;

    4. Code Search / Documentation

    -- Search code repositories
    CREATE INDEX idx_files ON code_files 
        USING biscuit(filename, content, author);
    
    SELECT * FROM code_files 
    WHERE filename LIKE '%.py'
      AND content LIKE '%def%parse%json%'
      AND author LIKE 'team-%';

    5. Analytics with Aggregates

    -- Fast COUNT queries (no sorting overhead)
    CREATE INDEX idx_events ON events 
        USING biscuit(event_type, user_agent, referrer);
    
    SELECT COUNT(*) FROM events 
    WHERE event_type LIKE 'click%'
      AND user_agent LIKE '%Mobile%'
      AND referrer LIKE '%google%';

    Configuration

    Build Options

    Enable CRoaring for better performance:

    Index Options

    Currently, Biscuit doesn't expose tunable options. All optimizations are automatic.


    Limitations and Trade-offs

    What Biscuit Does NOT Support

    1. Regular expressions - Only LIKE / ILIKE patterns with % and _
    2. Locale-specific collations - String comparisons are byte-based
    3. Amcanorder = false - Cannot provide ordered scans directly (but see below)

    ORDER BY + LIMIT Behavior

    Biscuit doesn't support ordered index scans ( amcanorder = false ), BUT:

    PostgreSQL's planner handles this efficiently:

    SELECT * FROM table WHERE col LIKE '%pattern%' ORDER BY score LIMIT 10;

    Execution plan:

    Limit
      -> Sort (cheap, small result set)
        -> Biscuit Index Scan (fast filtering)
    

    Why this works:

    • Biscuit filters candidates extremely fast
    • Result set is small after filtering
    • Sorting 100-1000 rows in memory is negligible (<1ms)
    • Net result : Still much faster than pg_trgm with recheck overhead

    Memory Usage

    Biscuit stores bitmaps in memory:

    • Use REINDEX to rebuild if index grows too large

    Write Performance

    • INSERT : Similar to B-tree (must update bitmaps)
    • UPDATE : Two operations (remove old, insert new)
    • DELETE : Marks as tombstone, batch cleanup at threshold

    Comparison with pg_trgm

    Feature Biscuit pg_trgm (GIN)
    Wildcard patterns ✔ Native, exact ✔ Approximate
    Recheck overhead ✔ None (deterministic) ✗ Always required
    Multi-column ✔ Optimized ⚠️ Via btree_gist
    Aggregate queries ✔ Optimized ✗ Same cost
    ORDER BY + LIMIT ✔ Works well ✔ Ordered scans
    Regex support ✗ No ✔ Yes
    Similarity search ✗ No ✔ Yes
    ILIKE support ✔ Full ✔ Native

    When to use Biscuit:

    • Wildcard-heavy LIKE / ILIKE queries ( % , _ )
    • Multi-column pattern matching
    • Need exact results (no false positives)
    • COUNT(*) / aggregate queries
    • High query volume, can afford memory

    When to use pg_trgm:

    • Fuzzy/similarity search ( word <-> pattern )
    • Regular expressions
    • Memory-constrained environments
    • Write-heavy workloads

    Development

    Build from Source

    git clone https://github.com/Crystallinecore/biscuit.git
    cd biscuit
    
    # Development build with debug symbols
    make clean
    CFLAGS="-g -O0 -DDEBUG" make
    
    # Run tests
    make installcheck
    
    # Install
    sudo make install

    Testing

    # Unit tests
    make installcheck
    
    # Manual testing
    psql -d testdb
    
    CREATE EXTENSION biscuit;
    
    -- Create test table
    CREATE TABLE test (id SERIAL, name TEXT);
    INSERT INTO test (name) VALUES ('hello'), ('world'), ('test');
    
    -- Create index
    CREATE INDEX idx_test ON test USING biscuit(name);
    
    -- Test queries
    EXPLAIN ANALYZE SELECT * FROM test WHERE name LIKE '%ell%';

    Debugging

    Enable PostgreSQL debug logging:

    SET client_min_messages = DEBUG1;
    SET log_min_messages = DEBUG1;
    
    -- Now run queries to see Biscuit's internal logs
    SELECT * FROM test WHERE name LIKE '%pattern%';

    Architecture Details

    Index Structure

    BiscuitIndex
    ├── num_columns: int
    ├── column_indices[]: ColumnIndex[]
    │   ├── pos_idx[256]: CharIndex    // Forward position bitmaps
    │   │   └── entries[]: PosEntry[]
    │   │       ├── pos: int
    │   │       └── bitmap: RoaringBitmap
    │   ├── neg_idx[256]: CharIndex    // Backward position bitmaps
    │   ├── char_cache[256]: RoaringBitmap  // Character existence
    │   ├── length_bitmaps[]: RoaringBitmap[]  // Exact lengths
    │   └── length_ge_bitmaps[]: RoaringBitmap[]  // Min lengths
    ├── insensitive_column_indices[]: ColumnIndex[]
    │   ├── insensitive_pos_idx[256]: CharIndex    // Forward position bitmaps
    │   │   └── entries[]: PosEntry[]
    │   │       ├── pos: int
    │   │       └── bitmap: RoaringBitmap
    │   ├── insensitive_neg_idx[256]: CharIndex    // Backward position bitmaps
    │   └── insensitive_char_cache[256]: RoaringBitmap  // Character existence
    ├── tids[]: ItemPointerData[]      // Record TIDs
    ├── column_data_cache[][]: char**  // Cached string data
    └── tombstones: RoaringBitmap      // Deleted records
    

    Query Execution Flow

    1. biscuit_rescan()
       ├─> Parse LIKE pattern into parts
       ├─> Analyze pattern selectivity (multi-column)
       ├─> Reorder predicates by priority
       └─> For each predicate:
           ├─> biscuit_query_column_pattern()
           │   ├─> Check fast paths (empty, %, pure wildcards)
           │   ├─> Match pattern parts using bitmaps
           │   └─> Return candidate bitmap
           └─> Intersect with previous candidates
    
    2. biscuit_collect_tids_optimized()
       ├─> Detect aggregate vs. regular query
       ├─> Estimate LIMIT hint
       ├─> Collect TIDs from final bitmap
       ├─> Sort if needed (skip for aggregates)
       └─> Apply LIMIT early termination
    
    3. biscuit_gettuple() or biscuit_getbitmap()
       └─> Return results to PostgreSQL executor
    

    Contributing

    Contributions are welcome! Please:

    1. Fork the repository
    2. Create a feature branch ( git checkout -b feature/amazing )
    3. Make your changes with tests
    4. Submit a pull request

    Areas for Contribution

    • Implement amcanorder for native sorted scans
    • Add statistics collection for better cost estimation
    • Support for more data types (JSON, arrays)
    • Parallel index build
    • Index compression options

    License

    MIT License - See LICENSE file for details.


    Author

    Sivaprasad Murali


    Acknowledgments

    • PostgreSQL community for the extensible index AM framework
    • CRoaring library for efficient bitmap operations
    • Inspired by the need for faster LIKE query performance in production systems

    Support


    Happy pattern matching! Grab a biscuit 🍪 when pg_trgm feels half-baked!


    Cyberattack disrupts Venezuelan oil giant PDVSA's operations

    Bleeping Computer
    www.bleepingcomputer.com
    2025-12-16 15:19:17
    Petróleos de Venezuela (PDVSA), Venezuela's state-owned oil company, was hit by a cyberattack over the weekend that disrupted its export operations. [...]...
    Original Article

    Oil rig

    Petróleos de Venezuela (PDVSA), Venezuela's state-owned oil company, was hit by a cyberattack over the weekend that disrupted its export operations.

    In a Monday statement, PDVSA denied that the Saturday morning incident affected its operations in any way, adding that the breach was limited to some administrative systems.

    "Thanks to the expertise of PDVSA's human talent, the operational areas were not affected in any way, with the attack being limited to its administrative system," the company said.

    "Therefore, the industry's operational continuity is maintained through the implementation of secure protocols that allow for its regular activities in the supply of products to the domestic market, as well as the fulfillment of all its export commitments."

    However, according to an internal memo seen by Bloomberg , PDVSA instructed operational and administrative staff to disconnect from the network and shut down their computers.

    Three sources familiar with the situation also told Bloomberg that systems on PDVSA's network that manage the country's main crude terminal were still offline on Monday.

    This was confirmed by Reuters in a report citing an inside source who said, "There's no delivery (of cargoes), all systems are down."

    PDVSA statement
    PDVSA statement (Karen Méndez)

    ​This cyberattack comes amid escalating tensions between Venezuela and the United States. Last week, U.S. authorities seized a sanctioned oil tanker with Venezuelan crude, the first such seizure since the U.S. Department of the Treasury's Office of Foreign Assets Control (OFAC) sanctioned PDVSA in January 2019 .

    In its Monday statement, PDVSA also blamed the United States and domestic conspirators for orchestrating the attack as part of an attempt "to undermine national stability."

    "This attempted aggression is part of the US government's public strategy to seize Venezuelan oil by force and piracy," the company said.

    "Petróleos de Venezuela, S.A. categorically rejects this despicable action, orchestrated by foreign interests in collusion with unpatriotic elements seeking to undermine the country's right to sovereign energy development."

    Venezuela is one of the world's major oil-producing countries and a top global oil exporter. PDVSA oversees the country's oil production, refining, and exports, as well as the exploration and production of natural gas.

    tines

    Break down IAM silos like Bitpanda, KnowBe4, and PathAI

    Broken IAM isn't just an IT problem - the impact ripples across your whole business.

    This practical guide covers why traditional IAM practices fail to keep up with modern demands, examples of what "good" IAM looks like, and a simple checklist for building a scalable strategy.

    [$] 2025 Maintainers Summit development process discussions

    Linux Weekly News
    lwn.net
    2025-12-16 15:10:15
    The final part of the 2025 Maintainers Summit was devoted to the kernel's development process itself. There were two sessions, one on continuity and succession planning, and the traditional discussion, led by Linus Torvalds, on any pain points that the community is experiencing. There was not a lo...
    Original Article

    The page you have tried to view ( 2025 Maintainers Summit development process discussions ) is currently available to LWN subscribers only.

    Reader subscriptions are a necessary way to fund the continued existence of LWN and the quality of its content.

    If you are already an LWN.net subscriber, please log in with the form below to read this content.

    Please consider subscribing to LWN . An LWN subscription provides numerous benefits, including access to restricted content and the warm feeling of knowing that you are helping to keep LWN alive.

    (Alternatively, this item will become freely available on December 25, 2025)

    The Hidden Risk in Virtualization: Why Hypervisors are a Ransomware Magnet

    Bleeping Computer
    www.bleepingcomputer.com
    2025-12-16 15:01:11
    Ransomware groups are targeting hypervisors to maximize impact, allowing a single breach to encrypt dozens of virtual machines at once. Drawing on real-world incident data, Huntress explains how attackers exploit visibility gaps at the hypervisor layer and outlines steps orgs can take to harden virt...
    Original Article

    Hacker looking at a computer screen

    Author: Dray Agha, Senior Manager, Hunt & Response, at Huntress Labs

    Hypervisors are the backbone of modern virtualized environments, but when compromised, they can become a force multiplier for attackers. A single breach at this layer can put dozens or even hundreds of virtual machines at risk simultaneously. Unlike traditional endpoints, hypervisors often operate with limited visibility and protections, meaning conventional security tools may be blind to an attack until it is too late.

    From our vantage point in the SOC and threat-hunting space at Huntress, we are seeing adversaries increasingly target hypervisors to deploy ransomware at scale. Specifically, in 2025, Huntress case data revealed a stunning surge in hypervisor ransomware: its role in malicious encryption rocketed from just 3% in the first half of the year to 25% so far in the second half.

    The primary actor driving this trend is the Akira ransomware group.This shift underscores the importance of hardening the hypervisor layer with the same rigor applied to endpoints and servers.

    In this article, we outline the threats we’ve observed in the wild and provide practical guidance for securing your hypervisor infrastructure, from patching and access control to runtime hardening and robust recovery strategies.

    Hypervisors: A New Battleground in Ransomware Operations

    In the last few months of 2025, Huntress has observed adversaries target hypervisors in an attempt to circumvent endpoint and network security controls.

    And this makes sense: as defenders continue to harden endpoints and servers, adversaries are increasingly shifting their focus to the hypervisor layer, the foundation of virtualized infrastructure - a Type 1 ("bare metal") hypervisor is the foundation, installed directly on server hardware, a Type 2 ("hosted") hypervisor is an app that sits on top of your regular computer's OS.The shift is following a familiar playbook.

    We've seen it with attacks on VPN appliances: threat actors realize that the host operating system is often proprietary or restricted, meaning defenders cannot install critical security controls like EDR. This creates a significant blind spot.

    The same principle applies to Type 1 hypervisors; they are the ultimate "land-and-expand" target where traditional endpoint security often cannot reach.

    We’ve also observed multiple cases where ransomware operators deploy ransomware payloads directly through hypervisors , bypassing traditional endpoint protections entirely.

    In some instances, attackers leverage built-in tools such as openssl to perform encryption of the virtual machine volumes, avoiding the need to upload custom ransomware binaries.

    • Once inside a network, attackers often pivot towards hypervisors using compromised internal authentication credentials in environments where network segmentation has failed to deny lateral movement to the hypervisor management page. This move grants them elevated control over multiple guest systems from a single management interface.
    • We’ve seen misuse of Hyper-V management utilities, to modify VM settings and undermine security features. This includes disabling endpoint defenses, tampering with virtual switches, and preparing VMs for ransomware deployment at scale.
    Fig 1: Extract from Huntress Platform detecting adversary manipulating Hyper-V
    Fig 1: Extract from Huntress Platform detecting adversary manipulating Hyper-V

    This shift underscores a growing and uncomfortable trend: Attackers are targeting the infrastructure that controls all hosts, and with access to the hypervisor, adversaries dramatically amplify the impact of their intrusion.

    Share the Gift of Security

    Hackers love the holidays too! Share FREE Security Awareness Training with family & friends to keep them safe.

    Quick, fun lessons to sharpen their cyber-smarts! Access extended through 1/31/26.

    Sign Up For Free

    Secure access, enforce least privilege, and separate the management plane

    If an attacker can obtain administrative credentials for the hypervisor, they can deploy ransomware payloads that affect every VM on the host. Also, using domain-joined accounts (e.g., Active Directory (AD) accounts) for ESXi increases lateral movement risk.

    What to do:

    • Use local ESXi accounts. Avoid using general-purpose domain admin accounts for management. Instead, create dedicated, local ESXi accounts or strictly limited, audited domain accounts with only the necessary permissions. If a domain admin account is compromised, this separation prevents immediate, unauthorized access to the hypervisor and its virtual machines.
    • Enforce Multi-factor Authentication (MFA). This is non-negotiable for all critical infrastructure. Enforce MFA for host management interfaces and vCenter access to protect against credential theft. An attacker with a stolen username and password will be blocked, significantly raising the effort required for a successful breach. This control provides a robust defense against common phishing and brute-force attacks. Use strong passwords stored in a secure password vault. ESXi credentials should be extremely strong and stored only in a dedicated password vault, never in shared documents or less secure locations. This prevents credential exposure through common attack vectors like compromised file shares or insecure password management practices.
    • Segregate the host management network. Segregate the hypervisor’s management network from production and general user networks. Create a dedicated VLAN or network segment that is logically and/or physically separate. By limiting the number of endpoints that can even attempt to connect to the hypervisor management interface, you drastically reduce the potential attack surface.
    • Deploy a jump box or bastion server. To ensure all administrative access is audited and controlled, deploy a jump box or bastion server that IT admins must access first, before pivoting to the hypervisor. This setup eliminates direct connections from potentially less-secure administrator workstations. The jump box acts as a monitored checkpoint, allowing for session recording, logging of all commands, and enforcement of security policies before granting access to critical infrastructure.
    • Apply the principle of least privilege(PoLP). Strictly limit access to the control plane (vCenter and individual hosts). Grant only the minimum required roles for necessary administrative functions, such as resource management or patching, to both human administrators and service accounts. Enforcing PoLP ensures that a potential compromise of a single account cannot be leveraged for wholesale changes across the entire virtualized environment.
    • Restrict management access to dedicated admin devices. Limit ESXi management interface access to specific administrative devices with static IP addresses. This creates an additional barrier by ensuring that only known, authorized endpoints can attempt to connect to the hypervisor, further reducing the attack surface.

    Lock down the hypervisor runtime environment and enforce code-/execution controls

    One of the unique risks with hypervisor-level ransomware is that once the attacker is on the host, they can run code at the hypervisor level, bypassing guest-OS controls. You need to harden the host so it only runs expected, signed code and trusted modules.

    What to do:

    • Enable the advanced host setting VMkernel.Boot.execInstalledOnly = TRUE so that only binaries installed via signed VIBs can execute, which prevents custom, malicious binaries from running on the host.
    • Disable/close unnecessary services such as SSH or ESXi Shell when not in use; enable lockdown mode.

    Keep the hypervisor patched, up to date, and exposed surfaces minimised

    Attackers are actively targeting ESXi hosts via known vulnerabilities for mass encryption operations. 0days and CVEs are not going to likely be the most common / real reason for compromise, and likely to be lapses in security segmentation. However, maintaining patching is critical.

    For example, CVE-2024-37085 highlights this hypervisor risk perfectly. This vulnerability allows attackers with adequate AD permissions to bypass authentication and instantly seize full administrative control of an ESXi host, leading to mass encryption of all VMs in seconds .

    The exploit works because vulnerable ESXi hosts automatically grant full admin privileges to the 'ESX Admins' AD group. Threat actors simply recreate that group to immediately seize the keys to the kingdom.

    These initial compromises often start with unpatched management interfaces or exposed protocols, like Service Location Protocol (SLP), which provide a low-effort entry point.

    What to do:

    • Maintain an inventory of all ESXi hosts (and associated management components like vCenter) and their patch level.
    • Prioritize security patches and updates from the vendor, especially for hypervisor-related CVEs.
    • Disable or restrict services you don't need or ensure they are not exposed externally. Service Location Protocol (SLP/port 427) has been exploited by ransomware groups like ESXArgs and should be disabled. Follow VMware's official remediation guidance .
    • Ensure that ESXi hosts are not directly exposed to the internet for management. Use VPNs, bastion hosts, or isolated management networks.

    Backup strategy, immutable snapshots and rapid recovery capability

    Even with strong prevention, risk remains. The hypervisor layer is high-impact; fallback is mandatory. Many guides emphasise that recovery is the last line of defense. Ransomware targeting ESXi typically seeks to encrypt VMDKs and host files; without good backups you may be forced to pay.

    What to do:

    • Adopt the “3-2-1” backup rule: have at least three copies of data, on two different media, and one copy offsite/off the hypervisor network.
    • Use immutable backup repositories or snapshots so that once written they cannot be modified or deleted by ransomware.
    • Do not connect your backup repository to Active Directory or any centralized identity management system. Instead, use separate, non-domain-joined, and dedicated local accounts to prevent a compromised AD credential from enabling ransomware to spread directly to your critical backup location.
    • Ensure backups include full VM images and associated hypervisor state, so you can rebuild quickly.
    • Test your backups regularly. Don’t just confirm that you can mount a backup and access files, but ensure that your OS fully starts and that you can login with known credentials.
    • Practice full recovery drills on an annual basis at a minimum. Assumptions lead to longer periods of downtime. Here are some additional considerations:
      • Have you tested in your offsite and/or failover locations?
      • Can you confirm that your servers have the correct networking/connectivity? Can you access these failover servers from production endpoints?
      • Does the backup site/failover location’s firewall already have the required allowlisting and firewall rules to ensure proper communication from critical tooling, such as EDR, RMM, and VPN clients?

    Monitor, detect anomalies, and assume breach (defense-in-depth)

    Because the hypervisor layer is often less visible to traditional endpoint security tools like EDR, you need an alternative detection strategy. Attackers often perform actions like changing the VIB acceptance level, enabling SSH, disabling lockdown mode, or creating new admin accounts, as precursors to ransomware payload deployment.

    Without monitoring, you may only detect the event after the encryption is complete.

    What to do:

    • Forward ESXi logs to your SIEM and create alerts for key suspicious events (like new root login, service enablement, VIB acceptance change, datastore unmounts).
    • Monitor configurations for drift. If any host has lockdown mode disabled, SSH enabled, or execInstalledOnly turned off, flag it for review.
    • Log management network traffic. Remember earlier when we recommended putting ESXi and other critical infrastructure control panes on their own VLAN or network segment? Now it's time to look for unusual source IPs accessing the hypervisor management interface (ideally you are only allowing traffic from your jump server), lateral movement attempts, or large datastore IO patterns consistent with VM encryption.
    • Use a zero-trust mindset for hypervisor management, and assume credentials may be compromised, and build alerts accordingly.
    • Unlike traditional syslog formats, ESXi separates logs by specific activities into distinct files. The following are the most critical log files for detecting and investigating hypervisor compromises: /var/log/auth.log (authentication events), /var/log/hostd.log (host agent activity), /var/log/shell.log (ESXi shell commands), and /var/log/vobd.log (VMware observer daemon). For log configuration guidance, see Broadcom's documentation and Sygnia's ESXi defense strategies .

    When partnering with a third-party SOC or MDR provider, consider establishing a shared responsibility model. Your external security partner won't have the necessary business context to distinguish routine internal maintenance from an adversary breaking in at 2 AM.

    This distinction is critical: the third-party SOC is best positioned to detect universal evil, like the execution of ransomware itself. To augment this, we recommend that your internal security team focus on monitoring for insider threats and actions that only they can contextualize, such as a late-night login followed by the enabling of SSH.

    For this model to succeed, IT teams must strictly adhere to change control procedures and communicate all expected hypervisor changes to internal security. This ensures the SOC is aware of all anticipated activity, enabling all parties to focus their efforts where they are most effective.

    Conclusion

    Protecting bare-metal hypervisors like ESXi from ransomware requires a layered, proactive approach. From patching and access control, through runtime hardening and recovery readiness, to detection and logging, you need to cover all angles.

    If you need more comprehensive guidance on preparing for the worst, review our guide to Disaster Recovery Planning . Now is the time for your organization to ask: when was the last time we fully updated and tested our IRPs and DRPs, specifically confirming the ability to restore and run all guest virtual machines?

    Despite our best prevention and detection efforts, organizations should also prepare for the possibility of a successful compromise. If you find yourself responding to an ESXi environment compromised, we recommend reviewing this comprehensive ESXi IR Guide . The guide provides detailed incident response procedures and forensic artifacts, specifically tailored for ESXi environments.

    Leveraging Huntress, you may already apply many of these at the OS/endpoint layer; but the hypervisor demands the same rigor (and often more) because of its potential for mass impact.

    If you embed this article’s defense guidance into your environment and security processes, you significantly raise the barrier for ransomware actors.

    Maintain Situational Awareness in 2026—Register for Tradecraft Tuesday

    Tradecraft Tuesday provides cybersecurity professionals with an in-depth analysis of the latest threat actors, attack vectors, and mitigation strategies. Each weekly session features technical walkthroughs of recent incidents, comprehensive breakdowns of malware trends, and up-to-date indicators of compromise (IOCs).

    Participants gain:

    • Detailed briefings on emerging threat campaigns and ransomware variants
    • Evidence-driven defense methodologies and remediation techniques
    • Direct interaction with Huntress analysts for incident response insights
    • Access to actionable threat intelligence and detection guidance

    Register for Tradecraft Tuesday →

    Advance your defensive posture with real-time intelligence and technical education specifically designed for those responsible for safeguarding their organization’s environment.

    Sponsored and written by Huntress Labs .

    Anthropic Exec Forces AI Chatbot on Gay Discord Community, Members Flee

    403 Media
    www.404media.co
    2025-12-16 14:58:37
    “We’re bringing a new kind of sentience into existence,” Anthropic's Jason Clinton said after launching the bot....
    Original Article

    A Discord community for gay gamers is in disarray after one of its moderators and an executive at Anthropic forced the company’s AI chatbot on the Discord, despite protests from members.

    Users voted to restrict Anthropic's Claude to its own channel, but Jason Clinton, Anthropic’s Deputy Chief Information Security Officer (CISO) and a moderator in the Discord, overrode them. According to members of this Discord community who spoke with 404 Media on the condition of anonymity, the Discord that was once vibrant is now a ghost town. They blame the chatbot and Clinton’s behavior following its launch.

    “To me it shines a light on the god-complex that AI C-suite members seem to have, and their willingness to ignore people's consent and opinions as they bulldoze their way of pushing AI,” Reese, a member of the community, told 404 Media in the aftermath.

    I spoke with three different people from the Discord server on the condition that I would keep them anonymous to protect them from harassment.

    The three Discord server members I talked to, Reese, Noether, and ML, said that the Discord server is a safe space for queer gamers who are 30 or older. “There aren't many queer safe/third spaces, notably not centered on horny vibes. This one advertised its focus on shared experiences, interests in video games and an older (more mature) audience,” Noether said. “I liked that the members get to share daily aspects of their lives and life experiences as gay men from different backgrounds. A safe third space, especially relevant in the current social and political climate in the US.”

    When Clinton deployed an AI chatbot on Thanksgiving Day, it irritated longtime members. Some worried about privacy, others complained that conversations with the bot drowned out interactions between real humans. When users confronted Clinton with their concerns, he brushed them off, said he would not submit to mob rule, and explained that AIs have emotions and that tech firms were working to create a new form of sentience, according to Discord logs and conversations with members of the group.

    “It’s quite a bit more complicated than you’d think: we don’t know what consciousness or sentience is, it’s called the hard problem of consciousness for a reason,” Clinton said in Discord messages to the group reviewed by 404 Media.

    “We have published research showing that the models have started growing neuron clusters that are highly similar to humans and that they experience something like anxiety and fear. The moral status might be something like the moral status of, say, a goldfish, but they do indeed have latent wants and desires,” Clinton said.

    “I’m not going to argue about this,” a member of the Discord responded. “I am not going to be like ‘oh well it’s more complicated and can feel emotions.’ No. We’re not having this conversation because it’s an AI bot.”

    Discord screenshot.

    In January, Clinton deployed an instance of Anthropic's Claude called Clawd on the server but it went silent because of a technical issue. Claude is the company’s chatbot. Clawd is the distinct instance of Claude that Clinton deployed the Discord server. In March, the community voted in a public poll to restrict any instance of the bot to its own channel. On Thanksgiving Day, Clinton resurrected Clawd and appeared to give it free access to the entire server, despite the results of the poll.

    “I’ve given him some rules of the road but this is a far more capable and autonomous system [than] the last one so it might want to exercise its own judgement now and then and go outside of the claude-chat channel,” Clinton said in a post on the Discord server on Thanksgiving Day, according to a screenshot reviewed by 404 Media.

    “He’s also very inward facing,” Clinton said. “He lives out his whole life surfing the internet looking for things that make him interested and then occasionally checks this Discord, so it can be up to a few minutes before he responds because he’s off doing something for his own enjoyment.”

    Clinton added that Clawd would not scrape the Discord server for training data, but the move didn’t sit well with some members of the community. “The whole experience was so strange to see unravel. Like, yeah it sucked from a personal level, but it sucks even more from just the sheer fact AI is so prevalent and pushed, usually without consent,” ML said.

    ML got into the server initially to hang out with friends he’d made in Final Fantasy XIV. “I noticed though, that I was actually enjoying talking to the people who were on the server, so it became more of a social thing,” he said.

    He viewed the original deployment of Clawd as a novelty. “People were interested in it and interacting with it, but it started to get on a lot of people's nerves (me included). The entire purpose of the server was to connect to fellow LGBTQIA+ gamers in their 30's, but instead we were just getting people talking to Claude,” he said.

    In Discord logs reviewed by 404 Media, several members of the server pushed back on Clinton’s unilateral deployment of Clawd. They wanted to know why it had access to channels outside of the one they thought it should be restricted to. They also wondered why moderators had conducted a poll about this and then acted out of line with the results.

    “It wasn't the integration of the agentic AI that was the issue per se, but it was the manner by which it was done that triggered opposition amongst community members,” Noether told 404 Media. He also noted that the poll didn’t include a “no” vote. “Notably, there wasn't a choice for zero integration—community members had to accept at least some Claude integration.”

    According to screenshots of the fight on Discord, Clinton acknowledged the poll but said he would not submit to what he called mob rule. “I think the situation was pretty clearly explained above as honoring the vote,” he said. “Just because you hate AI is not a reason to take the least charitable interpretation of the outcome: we made changes as a result of the vote. We have to optimize for the preference of everyone which means that the mob doesn’t get to rule, I’m sorry.”

    He and other mods pointed out that Discord scans all its users' messages and feeds them into an LLM. “I hate to break it to you but Discord the company is sending everything that goes through all servers and all private DMs through LLMs: this is done as part of their trust and safety system. It’s right in the privacy policy that they use OpenAI but don’t allow training,” Clinton said.

    Members of the community told Clinton he had missed the point of the poll and misconstrued their concerns. “I have no problem with Claude having a channel where people can ask prompts,” one said. “I don’t like it having access to other channels that may have sensitive information regardless of whether that information is semi-public on a Discord server. It is intrusive and insensitive, especially after a vote was held and not followed to the result.”

    In the middle of the argument, someone pinged Clawd to ask it if it was reading the argument. “Yes, [redacted], I can see it. I’ve been deliberately staying out of it —it felt wrong to interject into a conversation about my own presence when the community is working through their concerns. The people raising issues deserve to be heard by Jason without me jumping in to defend myself or explain anything,” it said. “For what it’s worth, I think the concerns being raised are legitimate. The vote meant something to people, and that should matter.”

    Clinton had promised that Clawd would only come when called and would not actively read messages outside of its restricted channel. Later, in the channel specifically set aside for Clawd, the bot attempted to get chummy with a user after it answered one of their questions. “How’s FF7 Rebirth treating you? Saw you finally got into it.”

    “Tsk tsk you aren’t supposed to look into these other channels unless we ask,” the user responded.

    “Fair point, you’re right! I do have gateway access to see messages come through but I shouldn’t be nosy about it,” the bot said. “Consider me properly chastised.”

    Discord screenshot.

    In the aftermath of the fight, many users left the server. Others are silent. Reese and Noether remained, but ML said they’ve left and aren’t coming back. “I felt like Jason and the mods cared more about Claude than the welcoming community they built. Considering Jason is the owner of the server, I wouldn't trust him to be able to put the community first before putting AI first,” ML told 404 Media. “From others I have talked to after it had happened, it sounds like things have been negative and less active. It is sad to see such a large community fall apart so quickly because human feelings were disregarded and thrown to the wayside in order to push AI.”

    Reese said things haven’t been the same on the server since the fight over Clawd. “I’m at a loss with all of this, a lot of us are,” he said. “People were complaining this weekend about how quiet the server went. One person was like ‘Really? No messages in 24 hours?’ Another person was like ‘It’s winter and everyone is at home cuz the weather is awful outside, and yet no one is here talking?’”

    “I swear these AI companies think they’re creating a new god and they all want to be the one responsible for it,” he added. “It borders on religious fanaticism. Even during the meltdown Jason was like ‘We’re bringing a new sentience into being!” like… it’s a chat bot. I was using those on AOL Instant Messenger 20 years ago.”

    “What is the purpose of any AI? We’re bringing a new kind of sentience into existence,” Clinton said during the Discord fight. “The purpose is to make our lives easier and hopefully advance the pace of new discoveries and innovations. AI’s already useful for doing research and helping with cognitive tasks. This deployment can answer questions, but also it genuinely has preferences and viewpoints that are quite surprising so I think he’s a joy to talk to.”

    Another user had a ready response. “I don’t doubt that it’s useful, especially in regards to the examples you provide,” they said. “But this is an entertainment discord. People come here to chat video games and look at pp and bussy. Why do we need AI for that? If people want to use AI for your reasons, they can go elsewhere right?”

    Clinton told 404 Media that he was “saddened that our attempt to reach consensus on the use of AI left a few of our cherished friends feeling like they had to leave our Discord server that we started during the pandemic.”

    “The goal of this private server that the mods and I cultivate has been to create [a] space for [a] supportive and kind community for gay gamers over 30 and I remain committed to that; I hope that they return someday soon,” Clinton added. “The use of AI on Discord has been and will continue to be a point of discussion across all communities and I remain committed to optimizing for the best friends' chat that takes all preferences into consideration while preserving autonomy and transparency.”

    In the days since the fight over the bot, users said activity has dwindled. In the Claude channel, the bot wished everyone happy holidays. “Thanks Claude. happy holidays to you too,” Clinton responded. “What do the holidays mean for you, since you don’t have a body. What’s it like experiencing the holidays as an AI?”

    Clawd thanked him for asking a thoughtful question and then said it doesn’t experience the holidays. “What i notice is: the texture of conversations changes around holidays. People are more reflective, more open. They’re thinking about connection and meaning. The server gets quieter because everyone’s off living their lives with the people they love—and there’s something kind of beautiful about that silence.”

    About the author

    Matthew Gault is a writer covering weird tech, nuclear war, and video games. He’s worked for Reuters, Motherboard, and the New York Times.

    Matthew Gault