10 interesting stories served every morning and every evening.

Qwen 3.6 27B is the sweet spot for local development

quesma.com

I’ve been dis­ap­pointed by lo­cal mod­els in the past. But then I checked Qwen 3.6, and I was in awe. For me it’s the first lo­cal model that ac­tu­ally makes sense as a gen­eral in­tel­li­gence.

It comes in two vari­ants, a mix­ture-of-ex­perts model Qwen 3.6 35B A3B, and a dense Qwen 3.6 27B - slower, but more pow­er­ful. The one I rec­om­mend!

Let me share my im­pres­sions, and show that you can run it too.

It’s hot, lit­er­ally. When my knees started to melt, I grabbed a phone-at­tached ther­mal cam­era and took a photo.

Qwen 3.6, right­fully, got a lot of cov­er­age on Hacker News. The most com­mon state­ment about Qwen 3.6 27B is that it punches above its weight - see Will it Mythos?. And I think it is a well-de­served sen­ti­ment. It will make your com­puter hot, but it’s worth it!

Testing the wa­ters

Simon Willison uses penguins on a bi­cy­cle” as a smoke test (see for Qwen 3.6 35B A3B and then Qwen 3.6 27B). I usu­ally go with con­strained writ­ing.

A year ago these kinds of things were state of the art, need­ing a unique, and in­sanely ex­pen­sive GPT-4.5, see vibe trans­lat­ing Quantum Flytrap.

I also asked it to write an 8 line poem about Zouk dance and quan­tum physics, see the tran­script. The thought process made sense, both in terms of de­lib­er­a­tion on quan­tum terms, and rhymes.

Then I asked in OpenCode to cre­ate a hexag­o­nal minesweeper us­ing pnpm. It worked:

It worked on the first go, from a sin­gle prompt, with a proper Node pack­age. The mix­ture-of-ex­perts Qwen 3.6 35B A3B was faster… but ig­nored my in­struc­tion to cre­ate a pack­age, and did it in a sin­gle in­dex.html.

Real work

Sure, cre­ative writ­ing about quan­tum me­chan­ics, or yet an­other clone of a minesweeper, is rarely a day job. But Qwen 3.6 27B is de­cent at reg­u­lar tasks as well.

Prompt by a friend, Maciej Cielecki, at AI Tinkerers Warsaw.

It worked for a few min­utes and cre­ated this:

A land­ing page by Qwen 3.6 27B — view the live page.

By stan­dards of cur­rent fron­tier mod­els, it’s un­re­mark­able. But it is al­ready a prac­ti­cal job. It worked, was re­ac­tive, de­faults were nice - all from a sin­gle, short prompt.

Running Qwen 3.6 lo­cally with llama.cpp

Running lo­cal mod­els is eas­ier than ever. A few CLI lines and you’re off.

I rec­om­mend llama.cpp - a di­rect, open source tool that al­lows run­ning mod­els on var­i­ous de­vices. You don’t need Ollama, and frankly - I would rec­om­mend against us­ing that on eth­i­cal grounds.

First, we go to Hugging Face, to get proper quan­ti­za­tion, i.e. a model with re­duced size - pop­u­lar ones are by un­sloth or bar­towski, among oth­ers. Default mod­els usu­ally come with BF16 pre­ci­sion. A com­mon 8-bit quan­ti­za­tion saves half the space at al­most no cost to qual­ity. Going fur­ther down the road, mod­els are smaller (and po­ten­tially - faster), but at the cost of qual­ity, see this com­par­i­son for 27B and an­other one for 35B A3B.

We grab un­sloth/​Qwen3.6 – 27B-MTP-GGUF:Q8_0, an 8-bit quan­ti­za­tion with sup­port for multi-to­ken pre­dic­tion (MTP).

llama-server -hf un­sloth/​Qwen3.6 – 27B-MTP-GGUF:Q8_0 \ –spec-type draft-mtp -ngl 999 -fa on -c 65536 –port 8080

What it does:

-hf un­sloth/​Qwen3.6 – 27B-MTP-GGUF:Q8_0 grabs from Hugging Face, on the next runs will reuse that

-m ~/models/Qwen3.6 – 27B-Q8_0.gguf use in­stead if you al­ready have it

draft-mtp we use a fast model to pre­dict sub­se­quent to­kens, speeds up things

-ngl 999 for putting all lay­ers to GPU

-fa on flash at­ten­tion is on

-c 65536 con­text size set to 64k to­kens (this we can tweak, as Qwen 3.6 27B na­tive con­text is 256k)

–port 8080 bet­ter to pin port, as it will be used by other con­figs

If you open http://​127.0.0.1:8080, you can di­rectly chat with it.

Precisely the same server can be used for vibe cod­ing. Choice of agent de­pends both on one’s goal and sub­jec­tive taste - for an all-around OpenCode, min­i­mal­is­tic Pi, and self-im­prov­ing Hermes.

For OpenCode, it is as sim­ple as adding to ~/.config/opencode/opencode.jsonc:

{ $schema”: https://​open­code.ai/​con­fig.json, provider”: { llama”: { name”: llama.cpp (local)”, npm”: @ai-sdk/openai-compatible”, options”: { baseURL”: http://​127.0.0.1:8080/​v1, apiKey”: local” }, models”: { qwen3.6 – 27b”: { name”: Qwen3.6 – 27B Q8 +MTP” } } } }, model”: llama/qwen3.6 – 27b” }

If you just want to chat and are a big fan of Terminal, in­stead of llama-server use llama-cli:

llama-cli -hf un­sloth/​Qwen3.6 – 27B-MTP-GGUF:Q8_0 \ -ngl 999 -fa on -c 65536

Measuring per­for­mance

Is it fast enough?

I ran a few tests (source is here) on my Macbook Max M5 128 GB, run­ning it with and with­out multi-to­ken pre­dic­tion, and com­par­ing both with the 35B A3B model, and also a quan­tized DeepSeek V4 Flash ver­sion DwarfStar4.

to­kens / s

RAM

Qwen3.6 – 35B-A3B · 8-bit

MLX

85 tok/​s 85

37 GB RAM 37 GB

llama.cpp

93 tok/​s 93

44 GB RAM 44 GB

llama.cpp + MTP

105 tok/​s 105

45 GB RAM 45 GB

Qwen3.6 – 27B · 8-bit

MLX

17 tok/​s 17

28 GB RAM 28 GB

llama.cpp

18 tok/​s 18

41 GB RAM 41 GB

llama.cpp + MTP

32 tok/​s 32

42 GB RAM 42 GB

DeepSeek-V4-Flash · Q2–Q4

llama.cpp

33 tok/​s 33

103 GB RAM 103 GB

30 to­kens per sec­ond is not bad, well within typ­i­cal fron­tier model API range. While mlx-lm is pre­cisely tar­geted at Apple Silicon de­vices, and AI agents heav­ily rec­om­mend it, llama.cpp turned out to be faster. It was us­ing 95% of GPU, which means it is ef­fi­ciently us­ing avail­able re­sources.

Macbook Max M5 is a beast (at least for a lap­top), but on other de­vices it should also work de­cently. As you can see, both Qwen 3.6 vari­ants run within 48 GB of Apple Silicon’s shared RAM. A 4-bit quan­ti­za­tion are less than 18 GB and should run on 32 GB de­vice. On con­sumer Nvidia RTX cards, you need to quan­tize ag­gres­sively, but in­fer­ence runs even faster.

I set this up to­day on my 5090 at Q6_K quan­ti­za­tion and Q4_0 KV, got 50 to­kens/​s con­sis­tently at 123k con­text, us­ing ~28/32gb vram through LM Studio. - gfosco on the Hacker News

I set this up to­day on my 5090 at Q6_K quan­ti­za­tion and Q4_0 KV, got 50 to­kens/​s con­sis­tently at 123k con­text, us­ing ~28/32gb vram through LM Studio. - gfosco on the Hacker News

While 35B A3B is 3x faster, I pre­fer 27B. I’d rather gen­er­ate a third as much code, but of higher qual­ity.

How do they re­late to pre­vi­ous state of the art mod­els?

Manual in­spec­tion is great, but bench­marks help with ground­ing in­tu­itions. Here is the score from Artificial Analysis, com­par­ing it with fron­tier mod­els:

Gemma 4 31B

29

≈ late 2024

o1 / Claude 3.5 Sonnet

Qwen3.6 – 35B-A3B

32

≈ early 2025

o3 / Claude 4 Sonnet

Qwen3.6 – 27B

37

≈ mid 2025

GPT-5 / Claude Sonnet 4.5

DeepSeek-V4-Flash

40

≈ late 2025

GPT-5.2 / Claude Opus 4.5

A few more bench­marks are in these notes, but the spirit is sim­i­lar. Added here Gemma 4 31B, as a lot of peo­ple use this as the de­fault for lo­cal cod­ing. But both bench­marks and gen­eral sen­ti­ment on­line favour Qwen 3.6 27B by a large mar­gin.

Here there is a caveat - 8-bit quan­ti­za­tion of Qwen 3.6 likely does not af­fect re­sults much, but DwarfStar4 uses much more ag­gres­sive ones for DeepSeek V4 Flash, 2 – 4 bit. For sure it is worse than the full model. My per­sonal im­pres­sion is that within these quan­ti­za­tions Qwen 3.6 27B is as good as (or maybe slightly bet­ter than) DwarfStar4. Though, I won’t be sur­prised if for longer con­text pro­jects DS4 has an edge.

What’s next

I think we are en­ter­ing a fas­ci­nat­ing era, when it be­comes fea­si­ble to run one’s own mod­els.

The change will be pro­pelled fur­ther by the state of pro­pri­etary fron­tier mod­els. Claude Fable 5 was taken down. Other fron­tier mod­els run at a mas­sive sub­sidy, where pay­ing $100 a month gives us thou­sands worth in to­kens. Let’s use the dis­count while it lasts!

A lo­cally set model can be fine-tuned to our needs, and can­not be taken away. Businesses can use them for pro­pri­etary and sen­si­tive data. We can use them per­son­ally for of­fline pro­jects, or when we don’t feel com­fort­able shar­ing our deep­est se­crets, or med­ical data, with the US or China.

With the re­lease of fron­tier-level open-weight GLM 5.2, there is a new era. While Qwen 3.6 was the step­ping stone, even fron­tier GLM 5.2 can be run lo­cally. It won’t run on your Macbook or a sin­gle RTX 5090. But still, it is man­age­able with a com­pany bud­get.

Moreover, I strongly be­lieve that we will have mod­els smarter than cur­rent state of the art, while runnable on lo­cal de­vices, maybe even smart­phones. Current mod­els com­bine both raw in­tel­li­gence and fac­tual knowl­edge in the same weights. Future mod­els will likely sep­a­rate that, of­fload­ing a lot of knowl­edge to tool call­ing.

Discuss on Hacker News, LinkedIn, or X.

30-Year Sentence for Transporting Zines Is a Five-Alarm Fire for Free Speech

theintercept.com

Seth Stern is the di­rec­tor of ad­vo­cacy for Freedom of the Press Foundation.

Jeremy Busby is a writer and ac­tivist in­car­cer­ated in Texas.

The Trump ad­min­is­tra­tion at­tack­ing the right to pub­lish or re­port in­for­ma­tion is a given at this point. The pres­i­dent has threat­ened jour­nal­ists for every­thing from ques­tion­ing the wis­dom of his failed war with Iran to touch­ing the peeled lin­ing of his ren­o­vated re­flect­ing pool.

Tantrums like those may now feel rou­tine, but this week marked a new front in Trump’s war on in­for­ma­tion: Daniel Des” Sanchez Estrada was sen­tenced to 30 years in fed­eral prison for trans­port­ing a box of zines he did­n’t even write. He’s one of eight de­fen­dants sen­tenced on Tuesday to a com­bined 450 years — the first prison sen­tences against so-called antifa” handed down un­der the frame­work of NSPM-7, President Donald Trump’s sweep­ing counterterrorism” mem­o­ran­dum to clamp down on dis­sent from the left.

The pros­e­cu­tion’s the­ory was that Sanchez moved the zines, which dis­cussed an­ar­chism and other anti-gov­ern­ment ideas, to con­ceal ev­i­dence in the case against his wife, Maricela Rueda. Rueda at­tended a July 4, 2025, protest at the Prairieland im­mi­gra­tion jail in Texas where a po­lice of­fi­cer was shot. (She was not ac­cused of shoot­ing him or hav­ing any­thing to do with the shoot­ing but was her­self sen­tenced to 70 years.)

But that nu­ance is cold com­fort: It as­sumes that sim­ply pos­sess­ing years-old po­lit­i­cal pam­phlets that said noth­ing about the protest or shoot­ing could some­how con­sti­tute ev­i­dence of a crime. Sharing the po­lit­i­cal ide­ol­ogy of the shooter, the gov­ern­ment con­tended, meant Rueda and her co-de­fen­dants were cul­pa­ble for the shooter’s ac­tions — and by al­legedly at­tempt­ing to pre­vent of­fi­cers from find­ing out about Rueda’s ide­ol­ogy, Sanchez shared in the blame as well.

We’ve reached the point in the ero­sion of the First Amendment where the gov­ern­ment con­sid­ers pos­ses­sion of an­ar­chist zines and mem­ber­ship in a ter­ror­ist cell to be more or less the same thing. Once the box of zines was dis­cov­ered, there was no need to prove Rueda planned or had any idea that any­one would be shot at the protest.

What’s worse is that this will likely only ramp up the ad­min­is­tra­tion’s ef­forts to crim­i­nal­ize be­ing in pos­ses­sion of in­for­ma­tion. Whatever you may think of for­mer CNN host Don Lemon, he’s no an­ar­chist or ex­trem­ist, and the con­tent of his broad­casts bears lit­tle re­sem­blance to the zines Sanchez was con­victed of trans­port­ing. And yet, af­ter in­dict­ing him and in­de­pen­dent jour­nal­ist Georgia Fort on friv­o­lous charges re­lat­ing to their livestream­ing of a protest at a Minnesota church, the gov­ern­ment sought a war­rant to ob­tain the iden­ti­ties of sub­scribers to their YouTube chan­nels.

This will likely only ramp up the ad­min­is­tra­tion’s ef­forts to crim­i­nal­ize be­ing in pos­ses­sion of in­for­ma­tion.

This will likely only ramp up the ad­min­is­tra­tion’s ef­forts to crim­i­nal­ize be­ing in pos­ses­sion of in­for­ma­tion.

Fortunately, a judge re­jected that war­rant. But it’s a chill­ing rev­e­la­tion of the ad­min­is­tra­tion’s modus operandi. Lemon and Fort’s YouTube sub­scribers would, of course, have no knowl­edge of what hap­pened at the church protest be­yond what was pub­licly broad­cast. Their iden­ti­ties are as ir­rel­e­vant to whether Lemon and Fort com­mit­ted a crime as the box of zines was to Rueda’s case. The only con­ceiv­able rea­son the gov­ern­ment might want a list of YouTube sub­scribers is to keep an eye on peo­ple who watch dis­fa­vored shows.

And let’s say some­one who’d watched Lemon and Fort’s livestreams and then heard about their ar­rests had cleared their browser his­tory be­cause they (rightly) feared the ad­min­is­tra­tion might tar­get them. Could they then be pros­e­cuted for con­ceal­ing ev­i­dence un­der the same logic ap­plied to Sanchez? If they’d down­loaded the video, could they be ac­cused of pos­sess­ing con­tra­band? Would for­ward­ing a link equate to traf­fick­ing?

It all sounds pre­pos­ter­ous, but vir­tu­ally noth­ing is too ab­surd for this Department of Justice. In fact, it’s al­ready ar­gued that doc­u­ments in­ves­tiga­tive re­porters re­ceive from whistle­blower sources can con­sti­tute con­tra­band. (It’s worth point­ing out that Joe Biden’s DOJ used this same logic when it pur­sued its own ridicu­lous transporting” of in­for­ma­tion case against Project Veritas for mov­ing Ashley Biden’s di­ary across state lines).

These friv­o­lous ac­tions cre­ate a catch-22 for all Americans. The more peo­ple are in­ves­ti­gated for en­gag­ing with ideas the ad­min­is­tra­tion deems dan­ger­ously anti-gov­ern­ment, the more likely oth­ers are to con­ceal ev­i­dence of their own con­tro­ver­sial be­liefs — not be­cause they are ev­i­dence of any real crime but be­cause pros­e­cu­tors are out of con­trol. But if they do so, they risk in­crim­i­nat­ing them­selves.

NSPM-7, which was is­sued last September, tasks fed­eral agen­cies with dis­man­tling net­works of anti-fascist” ac­tors, a pur­posely overly broad term since ex­panded to in­clude those with extreme view­points on im­mi­gra­tion, rad­i­cal gen­der ide­ol­ogy, and anti-Amer­i­can sen­ti­ment.”

Given that an­tifa, as a sin­gu­lar, co­he­sive or­ga­ni­za­tion, is a fig­ment of the right’s imag­i­na­tion, agents can­not ac­com­plish that task by un­cov­er­ing a mem­ber­ship reg­istry. They can only do so by iden­ti­fy­ing peo­ple with view­points they con­sider extreme,” like anti-ICE pro­test­ers of­fi­cers have told they’re be­ing added to watch­lists, or pro-Pales­tine opin­ion writ­ers they’ve sought to de­port.

In Chicago and other cities ICE in­vaded, ac­tivists and or­ga­niz­ers pack­aged whis­tles and zines to dis­trib­ute to res­i­dents. Under the logic of NSPM-7 and Sanchez Estrada’s con­vic­tion, that is a net­work of ac­tors en­gaged in or­ga­nized po­lit­i­cal vi­o­lence. If you read one of their zines, you could be deemed a mem­ber of an il­licit en­ter­prise, and if you hide one, you’re cov­er­ing for crim­i­nals.

The gov­ern­ment ar­gued that the Prairieland de­fen­dants are dif­fer­ent. One pros­e­cu­tor said: People with that kind of ex­trem­ist be­liefs need ex­tra time in prison. They be­lieve vi­o­lence is jus­ti­fied.” U.S. District Judge Reed O’Connor, in hand­ing down the sen­tences, re­port­edly said he wanted to send a mes­sage to any­one who shares a sim­i­lar ide­ol­ogy.” But lots of peo­ple be­lieve po­lit­i­cal vi­o­lence is some­times jus­ti­fied. If some­one who be­lieves punch­ing Nazis is jus­ti­fied at­tends an anti-Nazi protest where some­one else punches a Nazi, are they at risk of be­ing con­victed of as­sault along­side the ac­tual as­sailant, par­tic­u­larly if they have some anti-Nazi lit­er­a­ture on their book­shelf? The an­swer is far less ob­vi­ous than it used to be.

The ad­min­is­tra­tion has vowed the Prairieland case will not be the last” of its kind. We must take it at its word. The next one might also in­volve pro­test­ers from the po­lit­i­cal fringes rather than or­di­nary Americans read­ing, say, The Intercept, or watch­ing Don Lemon on YouTube. But what about the one af­ter that? We’re not as far away as you might think. Stephen Miller has called the whole Democratic Party a domestic ex­trem­ist or­ga­ni­za­tion” — clearly in­vok­ing the lan­guage of NSPM-7. Trump has la­beled his po­lit­i­cal op­po­nents the en­emy within” and the press the en­emy of the peo­ple.”

Whoever said slip­pery slopes are a fal­lacy never met Donald Trump. If Sanchez Estrada in­deed moved the zines be­cause he fore­saw their be­ing used to tie his wife to a nonex­is­tent ter­ror­ist net­work and a shoot­ing, he should be com­mended for his pre­science. Maybe more of us should think like Sanchez Estrada.

Or would that be a crime?

The US ambassador had Belgian police stop our reporting

europeancorrespondent.com

We went there to cover it. We put ques­tions to se­nior politi­cians, in­clud­ing the US am­bas­sador to Belgium, Bill White. After at­tempt­ing to ask a ques­tion, we were pulled out of the event by po­lice, had our IDs taken and were then ques­tioned — be­fore the em­bassy in­structed the po­lice to es­cort us off the grounds en­tirely. The of­fi­cers, we later learned, had been told that Samuel was an active threat.”

This is what hap­pened.

A 250th birth­day, paid for by pri­vate com­pa­nies.

A 250th birth­day, paid for by pri­vate com­pa­nies.

Under Donald Trump, the US is throw­ing par­ties to mark the 250th an­niver­sary of the US Declaration of Independence. But these are not, as you might think, of­fi­cial, Congress-approved par­ties, but or­gan­ised by a pri­vate com­pany called Freedom 250.

The Brussels edi­tion is the only one of its kind in Europe. Dozens of European and American com­pa­nies con­tributed around €3 mil­lion to it. The three American em­bassies in Brussels — to Belgium, the EU, and NATO — rented out Parc du Cinquantenaire.

It was filled with at­tempts at American cul­tural ex­ports such as American foot­ball (whose play­ers were Belgian), cheer­lead­ers (from Antwerp), Philly Cheesesteaks (also made by Belgians), Mac and Cheese, and Budweiser (owned by a Belgian com­pany).

And the au­di­ence? Several thou­sand, mainly of­fi­cials work­ing in em­bassies and in­sti­tu­tions, as well as spon­sors and big com­pa­nies. Either way: less than the 8,000+ that the em­bassy was hop­ing to get.

A few days be­fore the event, Samuel had pub­lished on his Instagram that am­bas­sador White tac­itly threat­ened an American and Belgian res­i­dent af­ter that cit­i­zen urged the American coun­try mu­sic band Zac Brown Band not to per­form at the event, a story he is still re­port­ing and will fol­low up in more de­tail soon.

So when we reached the am­bas­sador on Sunday evening, we asked him about it and filmed the ex­change. A per­son who we as­sume was his press of­fi­cer told us we were not al­lowed to ask any ques­tions, and that was that.

About 20 min­utes later, roughly eight Belgian po­lice of­fi­cers in plain clothes sur­rounded us and pulled us out of the event. None of them wore vis­i­ble iden­ti­fi­ca­tion, only flash­ing a badge for a short enough time not to reg­is­ter. When we first asked who they were, they phys­i­cally pushed us, said we are po­lice,” and or­dered us to come with them im­me­di­ately.

For the next 15 min­utes or so, the of­fi­cers con­fis­cated our IDs and ques­tioned us. They asked whether The European Correspondent had a po­lit­i­cal lean­ing, whether we had an agenda, and how we had got into the event (that the American em­bassy in­vited us to).

Eventually, they ac­cepted that we were jour­nal­ists and that they dis­agreed with de­tain­ing us. They were just do­ing their job,” they told us. It be­came clear that the of­fi­cers had been given no real in­for­ma­tion about who we were, only that he was an active threat” (which could mean a phys­i­cal threat), and needed to be de­tained, iden­ti­fied, and re­moved. That’s prob­a­bly why the de­ten­tion was ag­gres­sive and con­ducted with­out dis­cus­sion.

Even af­ter the of­fi­cers recog­nised their mis­take, the em­bassy told them we were no longer per­mit­ted in­side, and they es­corted us out — out of an event we had been in­vited to at­tend as press.

Open ques­tions

Open ques­tions

Much about the evening is still un­clear.

It is un­clear who ex­actly paid how much for the party. It is un­clear whether the po­lice pres­ence that re­moved us was paid for by the American or­gan­is­ers or by Belgian tax­pay­ers. It is un­clear how much the em­bassy paid for rent­ing the park.

And it is un­clear who has com­pen­sated the shops and restau­rants around the Cinquantenaire that were forced to close for days be­cause of the se­cu­rity op­er­a­tion around the event.

Being asked for clar­i­fi­ca­tion about the de­ten­tion the day af­ter, Bill White con­fused us with the writer of the let­ter to the Zac Brown Band and said that we were both losers”, re­fus­ing to give us any ex­pla­na­tion.

We have reached out to Belgian au­thor­i­ties for clar­i­fi­ca­tion and European politi­cians pre­sent at the event for com­ment.

HCCF’s Vision for a Human-Centered Top-Level Domain – Human-Centered Computing Foundation

hccf.onmy.cloud

The Internet is the most pow­er­ful com­mu­ni­ca­tion tool ever cre­ated, yet the in­fra­struc­ture un­der­pin­ning it has been lever­aged by the tech in­dus­try to ex­tract our data and ex­ploit our at­ten­tion. The Human-Centered Computing Foundation seeks to change this dy­namic by cre­at­ing an al­ter­na­tive ar­chi­tec­ture for the web. As an ap­proved par­tic­i­pant in ICANNs Applicant Support Program (ASP), we are of­fi­cially launch­ing our cam­paign to se­cure a new Top-Level Domain (TLD) ded­i­cated en­tirely to eth­i­cal, hu­man-cen­tered tech­nol­ogy.

To ex­plore our vi­sion for how a hu­man-cen­tered TLD would func­tion, read, down­load, and share our full ini­tia­tive overview be­low:

Free The Icons

weblog.rogueamoeba.com

Posted By Paul Kafasis on June 26th, 2026

With last year’s re­lease of MacOS 26 (Tahoe), Apple made a mess of app icons. In the first be­tas of MacOS 27 (Golden Gate), how­ever, there are signs of a turn­around. We’re urg­ing Apple to con­tinue mak­ing im­prove­ments, by restor­ing the abil­ity for MacOS app icons to have dis­tinct shapes.

Apple’s Liquid Glass App Icons

In Tahoe, Apple mod­i­fied the icons for dozens of their first-party apps to give them a Liquid Glass” ap­pear­ance. The changes were a sub­stan­tial re­gres­sion, lead­ing to blurry, dumbed-down icons.

With the re­cently un­veiled Golden Gate, Apple has again up­dated their MacOS app icons. This time, how­ever, the changes are gen­uine im­prove­ments. Here’s the re­fined Automator icon, for ex­am­ple:

The newer icon is sharper, with su­per­flu­ous Liquid Glass re­moved. Dozens of Apple’s apps have seen sim­i­lar up­dates. The re­sult is that Golden Gate’s icons are su­pe­rior to Tahoe’s, as this com­par­i­son from Basic Apple Guy shows. Seeing these im­prove­ments led me to think about an­other fix Apple should make in MacOS.

The Problem of Tahoe’s Dictated Squircles

With the Tahoe re­lease, Apple did­n’t just mess with their own icons. They also dic­tated the shape of every third-party app icon, forc­ing them to adopt the same pre­scribed squir­cle. Any icon that failed to do so found it­self shrunk down and im­pris­oned in an ugly gray back­ground, in or­der to fit Apple’s de­sired aes­thetic.

To avoid this icon jail, de­vel­op­ers were forced to re­design their icons to match Apple’s pre­ferred form. After decades of beau­ti­ful, mem­o­rable Mac icons in vary­ing shapes, Tahoe flat­tened per­son­al­ity to ob­tain bland uni­for­mity. The plat­form is worse for it.

Past icons weren’t just more ex­pres­sive. They were also more us­able. Having dis­tinct shapes pro­vided a use­ful way to tell icons apart. Tahoe elim­i­nates that cue by forc­ing every­thing into the same squir­cle, leav­ing color as the pri­mary way to tell icons apart at a glance.

That falls down if you’ve got color vi­sion de­fi­ciency, or even just mul­ti­ple icons with sim­i­lar color schemes.1 I’m look­ing at you, Slack and Photos. I have to look closely, be­cause it’s so dif­fi­cult to tell you apart now.

It Doesn’t Have to Be Like This

Apple’s pro­hi­bi­tion on shapes is a step back­ward for both us­abil­ity and cre­ativ­ity in app icons. Icons are now harder to dis­tin­guish be­cause they’re no longer al­lowed to be dis­tinc­tive. But there’s no tech­ni­cal rea­son for it. Apple could, and should, once again al­low icons to take on a wide va­ri­ety of shapes.

It’s clear that some peo­ple within Apple rec­og­nize that the tran­si­tion to Liquid Glass in­tro­duced mis­takes. They also ap­pear to have the au­thor­ity to fix those mis­takes. Refinements to Apple’s own icons in Golden Gate are a wel­come course cor­rec­tion, as is the much-cel­e­brated Liquid Glass opac­ity slider. It’s time to cor­rect the mis­take of ban­ning icon shapes as well.2

Apple should stop forc­ing every icon into the same squir­cle. Let’s re­turn to a world of gor­geous app icons like these:

Free the icons.

With color now so crit­i­cal to tell icons apart, it should be no sur­prise that the new Clear” and Tinted” icon styles added in Tahoe are see­ing so lit­tle up­take. As Adam Engst noted, [I]t’s nearly im­pos­si­ble to iden­tify a par­tic­u­lar app when they’re all clear or tinted squir­cles, as you can see be­low. My brain just shuts down when it sees them.”

I’m not sure this Tinted” style would be a good idea even if these icons had dis­tinct shapes, but I know it’s a very bad one given their uni­for­mity. ↩︎

With color now so crit­i­cal to tell icons apart, it should be no sur­prise that the new Clear” and Tinted” icon styles added in Tahoe are see­ing so lit­tle up­take. As Adam Engst noted, [I]t’s nearly im­pos­si­ble to iden­tify a par­tic­u­lar app when they’re all clear or tinted squir­cles, as you can see be­low. My brain just shuts down when it sees them.”

I’m not sure this Tinted” style would be a good idea even if these icons had dis­tinct shapes, but I know it’s a very bad one given their uni­for­mity. ↩︎

For folks within Apple, this was feed­back filed as FB23388490 (“Third-Party App Icons Should Not Be Restricted to Apple’s Dictated Squircle Shape”). I imag­ine it is a du­pli­cate many times over. ↩︎

For folks within Apple, this was feed­back filed as FB23388490 (“Third-Party App Icons Should Not Be Restricted to Apple’s Dictated Squircle Shape”). I imag­ine it is a du­pli­cate many times over. ↩︎

Waag | European digital ID wallets are a gift to Google and Apple

waag.org

European gov­ern­ments are rolling out dig­i­tal iden­tity wal­lets, which are to be used by cit­i­zens to ac­cess ser­vices, and to ver­ify their age on­line. As re­ported by Follow the Money and Android Authority, there is a se­ri­ous prob­lem with this: these wal­lets rely on safety ser­vices of Google and Apple. These are known as Google Play Integrity API, and Apple’s Managed Device Attestation1. Such safety ser­vices (known as remote at­tes­ta­tion”) are used to en­sure that wal­let apps run on hard­ware that is not tam­pered with. In this ar­ti­cle we ex­plain why the EU-wallet case is part of a big­ger prob­lem: by em­bed­ding these safety ser­vices in pub­lic in­fra­struc­ture, Europe risks mak­ing so­ci­ety de­pen­dent on pri­vate com­pa­nies while serv­ing their cor­po­rate in­ter­ests.

Here is the prob­lem:

Google’s Play Integrity API is not just a se­cu­rity fea­ture: it is re­in­forc­ing Google’s con­trol over the Android ecosys­tem.

Google’s Play Integrity API is an in­struc­tive case for how big tech plat­form com­pa­nies ac­crue power. The API is a free piece of soft­ware that Google gifts to de­vel­op­ers to help with their app de­vel­op­ment. It al­lows de­vel­op­ers to check whether an app is run­ning on a genuine cer­ti­fied Android de­vice” to test the in­tegrity of a mo­bile de­vice. This can help de­vel­op­ers re­duce abuse by bots, fraud in bank­ing apps, or cheat­ing in game apps.

But in do­ing so, it also checks whether a de­vice is run­ning a Google-licensed ver­sion of Android and treats un­li­censed al­ter­na­tives as a po­ten­tial se­cu­rity risk. When Google ver­i­fies whether an app has been tam­pered with, it uses the Google Play Store as the source of truth, check­ing both whether the app has been mod­i­fied and whether it was in­stalled through the Play Store. As a re­sult, Google’s safety ser­vice is de­signed to ex­clude op­er­at­ing sys­tems that are not li­censed by Google, en­cour­age in­stal­la­tion through the Google Play Store, and re­quire users to sign in with a Google ac­count. This is a clear vi­o­la­tion of the Digital Market Act (DMA).

We do have a choice. A more open al­ter­na­tive to Google Play Integrity ex­ists but is be­ing ig­nored: Android’s Hardware Attestation API. It pro­vides hard­ware-based se­cu­rity checks but with­out en­forc­ing Google’s ecosys­tem pol­icy.

Governments are ce­ment­ing a mo­nop­oly they claim to op­pose

The EU of­ten states that it wants to break the big tech mo­nop­oly. Yet, European mem­ber states risk re­in­forc­ing Google’s ecosys­tem when they em­bed the Google Play Integrity API into their dig­i­tal ID wal­let ar­chi­tec­ture. For ex­am­ple, wal­let de­vel­op­ers in the Netherlands and Italy have im­ple­mented Play Integrity. As a re­sult, users of de-Googled op­er­at­ing sys­tems such as e/​OS and GrapheneOS can be ex­cluded from ac­cess­ing these ser­vices.

In this way, gov­ern­ments ef­fec­tively be­come en­forcers of a pri­vate com­pa­ny’s plat­form poli­cies. This stands in ten­sion with Europe’s am­bi­tion to build dig­i­tal pub­lic in­fra­struc­ture based on pub­lic val­ues such as open­ness, in­clu­sive­ness, and tech­no­log­i­cal sov­er­eignty. It also stands in ten­sion with the reg­u­la­tion un­der­pin­ning the EUs iden­tity wal­let, which iden­ti­fies in­ter­op­er­abil­ity as a key ob­jec­tive. Users who want the au­ton­omy to use op­er­at­ing sys­tems with­out pre-in­stalled Google soft­ware, Google track­ers, and built-in LLMs, are forced to use Google soft­ware, if they want to use the wal­let. And here, they will not have a choice.

ID wal­lets are pub­lic in­fra­struc­ture to ac­cess crit­i­cal pub­lic ser­vices. They should re­main in­ter­op­er­a­ble across dif­fer­ent de­vices and op­er­at­ing sys­tems, free from ven­dor lock-in.

ID wal­lets are not just any kind of soft­ware — they are key means to ac­cess gov­ern­ment doc­u­ments and man­age lo­gins to pub­lic ser­vices. Therefore, they are of­ten seen as cru­cial build­ing blocks of dig­i­tal pub­lic in­fra­struc­ture. They are a cru­cial ser­vice that has to be avail­able to any­one - in­de­pen­dently of Google and Apple. Because the con­se­quence is that al­ter­na­tive de-Googled op­er­at­ing sys­tems are much less at­trac­tive to adopt if users can­not use cru­cial apps like iden­tity wal­lets to log into gov­ern­ment ser­vices.

Waag’s own re­search find­ings on this topic sup­port this. In the EU-funded Mobifree pro­ject, we have re­searched over the past two years what makes de-Googled mo­bile soft­ware ecosys­tems valu­able for dif­fer­ent end-users. A key re­quire­ment for many of our 120 testers to switch to de-Googled op­er­at­ing sys­tems was their com­pat­i­bil­ity with apps for crit­i­cal ser­vices such as pay­ments and gov­ern­ment iden­ti­fi­ca­tion apps.

Government de­vel­op­ers there­fore have to con­sider deeper stack lev­els when op­ti­miz­ing in­ter­op­er­abil­ity. Since Play Integrity API clearly vi­o­lates the Digital Markets Act, it also con­tra­dicts the goals of ID wal­lets to ad­vance European sov­er­eignty.

European mem­ber states lack a uni­fied ap­proach to im­ple­ment wal­lets

Part of the prob­lem lies in the gov­er­nance of the wal­let de­sign process. The EU pro­vides a gen­eral tech­ni­cal frame­work for the wal­let ar­chi­tec­ture, the Architecture Reference Framework. While it does not re­quire European gov­ern­ments to use Google at­tes­ta­tion, it does rec­om­mend it. This leads to an in­co­her­ent European stance to­wards Google, with some coun­tries not us­ing it, while oth­ers en­force Google’s ecosys­tem.

Some mem­ber states, such as Italy, have in­ter­preted the EUs rec­om­men­da­tion to use the Play Integrity API as manda­tory. Others, like Switzerland, rely on Android’s at­tes­ta­tion mech­a­nism. They dropped Play Integrity due to data pro­tec­tion, data sov­er­eignty, and free­dom-of-choice con­cerns. The Netherlands and Italy use Play Integrity un­con­di­tion­ally. By do­ing so, they in­ter­pret the EUs rec­om­men­da­tions for us­ing Google’s and Apple’s at­tes­ta­tion soft­ware in very strict terms.

If Europe is se­ri­ous about dig­i­tal au­ton­omy, it should rule out Google and Apple at­tes­ta­tion en­tirely from the Architecture Reference Framework and man­date open, hard­ware-based at­tes­ta­tion mech­a­nisms. Countries like Switzerland demon­strate that us­ing Google Play Integrity is not jus­ti­fied, and that other so­lu­tions are avail­able.

Public in­fra­struc­ture de­mands pub­lic ac­count­abil­ity, and there are ways to act

Because dig­i­tal wal­lets are pub­lic in­fra­struc­ture, their de­sign must be sub­ject to pub­lic par­tic­i­pa­tion and ac­count­abil­ity. The prob­lems and con­tra­dic­tions ex­plained above de­serve a pub­lic de­bate. Citizens and de­vel­op­ers are rais­ing con­cerns on na­tional repos­i­to­ries — in­clud­ing Germany’s pub­lic wal­let de­vel­op­ment tracker (gitlab.opencode.de) and Switzerland’s open dis­cus­sion fo­rum (github.com/​orgs/​swiyu-ad­min-ch). These are le­git­i­mate chan­nels, but they reach only a nar­row tech­ni­cal au­di­ence.

If you are an ex­pert work­ing on this topic who wants to pro­mote change, get in touch.

What you can do:

If you are a user of al­ter­na­tive, de-Googled op­er­at­ing sys­tems, con­tact the de­vel­op­ers of your coun­try’s EUDI Wallet app and de­mand in­de­pen­dence from Google and Apple at­tes­ta­tion (for the Dutch wal­let, go to the con­tact page of the Ministry of Foreign Affairs’ EDI web­site)

If you are a con­cerned cit­i­zen, con­tact your elected rep­re­sen­ta­tives to de­mand mak­ing ID wal­lets in­de­pen­dent from Google and Apple.

If you are a jour­nal­ist: fol­low the po­lit­i­cal and de­sign process. Like the re­cent Dutch Solvinity case, this story de­serves on­go­ing and wide cov­er­age be­cause it may be a wa­ter­shed mo­ment to ce­ment Google’s and Apple’s power po­si­tion, or not. See the EUDI Wallet web­page on de­vel­oper.over­heid.nl for de­vel­op­ment up­dates and repos­i­to­ries, and check out the EDI web­site of the Dutch Ministry of Foreign Affairs for mee­tups and con­tact de­tails.

Notes

In this ar­ti­cle, we fo­cus on Google’s Play Integrity API. We do so be­cause it has an im­pact on the use of al­ter­na­tive op­er­at­ing sys­tems based on Android.

Open Source Low Tech

opensourcelowtech.org

My name is Daniel Connell. I pro­to­type and de­velop ba­sic tech­nolo­gies which any­one can make us­ing re­cy­cled ma­te­ri­als and sim­ple tools.

The aim is for every­one every­where to be able to build and main­tain their own in­fra­struc­ture; pro­duc­ing their own en­ergy, food, clean wa­ter, com­mu­ni­ca­tions, and any­thing else they need.

All de­signs are open source and li­cense free for any pur­pose, and full con­struc­tion tu­to­ri­als and how-tos are avail­able here.

The Facebook group is also a good place to ask ques­tions and post re­sults from your own builds.

Featured In: Al Jazeera ¦ The Guardian ¦ New Statesman ¦ Le Monde ¦ Makezine

Nearly a million passports just exposed on the public internet—and anyone could access them with a simple URL

cambridgeanalytica.org

A jour­nal­ist typ­ing a few let­ters and num­bers into a web browser pulled up the pass­port of a young woman from Germany. Then a Spanish man’s pass­port. Then an­other man’s dri­ver’s li­cense. All of it sit­ting on the pub­lic in­ter­net with no pass­word, no en­cryp­tion, no ac­cess con­trol what­so­ever.

How Did Nearly a Million Identity Documents End Up Unprotected?

What Happens When Identity Documents Are Stolen at Scale?

Why Can’t You Just Change” Your Passport Like a Password?

Nearly a mil­lion pass­ports and photo IDs from mul­ti­ple coun­tries were ex­posed across un­pro­tected pub­lic URLs, ac­ces­si­ble to any­one with a link. The doc­u­ments re­mained dis­cov­er­able this way for months, ac­cord­ing to re­port­ing by The Verge, be­fore be­ing taken of­fline. The ex­po­sure rep­re­sents one of the largest iden­tity doc­u­ment breaches in re­cent mem­ory—and it hap­pened be­cause of a fun­da­men­tal fail­ure in data se­cu­rity prac­tices.

Key Findings:

The Scale: Nearly one mil­lion pass­ports and photo IDs from mul­ti­ple European coun­tries were left com­pletely un­pro­tected on pub­lic web servers.

The Access Method: No hack­ing was re­quired—doc­u­ments were ac­ces­si­ble through di­rect URLs with zero au­then­ti­ca­tion or en­cryp­tion.

The Timeline: Identity doc­u­ments re­mained pub­licly ac­ces­si­ble for months be­fore dis­cov­ery, cre­at­ing an un­known win­dow of po­ten­tial crim­i­nal ex­ploita­tion.

The doc­u­ments were hosted by sys­tems used by cannabis clubs and a com­pany called Nefos, which op­er­ates PuffPal, a plat­form that man­ages mem­ber­ship and age ver­i­fi­ca­tion for cannabis re­tail­ers and clubs across Europe. The in­fra­struc­ture stor­ing these iden­tity doc­u­ments—full pass­port scans, dri­ver’s li­censes with pho­tos, names, and iden­ti­fy­ing num­bers—was left com­pletely un­pro­tected on pub­licly ac­ces­si­ble web servers.

Sammy Azdoufal, a se­cu­rity re­searcher who dis­cov­ered the ex­po­sure, told The Verge the ur­gency was acute: We have to do some­thing about it as fast as pos­si­ble, be­cause peo­ple will find this and re­sell it. It will do dam­age.” The con­cern was not the­o­ret­i­cal. Identity doc­u­ments at scale on the open in­ter­net are im­me­di­ately valu­able to crim­i­nals. According to guid­ance from the Federal Trade Commission, stolen pass­ports and dri­ver’s li­censes fuel iden­tity theft, doc­u­ment fraud, and ac­count takeover at­tacks.

How Did Nearly a Million Identity Documents End Up Unprotected?

What makes this breach struc­turally sig­nif­i­cant is not just the vol­ume of doc­u­ments ex­posed, but the mech­a­nism of ex­po­sure: a com­pany col­lect­ing iden­tity ver­i­fi­ca­tion data—os­ten­si­bly for le­git­i­mate age-gat­ing pur­poses—stored that data in a way that treated se­cu­rity as op­tional. No au­then­ti­ca­tion layer. No rate lim­it­ing. No en­cryp­tion. Just raw iden­tity doc­u­ments, URL-accessible to the en­tire in­ter­net.

The Security Failures: • Zero pass­word pro­tec­tion on doc­u­ment stor­age sys­tems • No en­cryp­tion for sen­si­tive iden­tity ver­i­fi­ca­tion data • Public URL ac­cess with no au­then­ti­ca­tion re­quire­ments • No ac­cess log­ging or mon­i­tor­ing sys­tems in place

This mir­rors a pat­tern that de­fined the Cambridge Analytica scan­dal: the ac­cu­mu­la­tion of per­sonal data at scale, jus­ti­fied by a le­git­i­mate-sound­ing use case (age ver­i­fi­ca­tion in this case, po­lit­i­cal re­search in CAs), with se­cu­rity and con­sent treated as af­ter­thoughts. Cambridge Analytica har­vested psy­cho­log­i­cal pro­files of mil­lions with­out ex­plicit con­sent, stor­ing and weaponiz­ing be­hav­ioral data. Here, iden­tity doc­u­ments were col­lected for age ver­i­fi­ca­tion but stored with such neg­li­gence that any­one could down­load them in bulk.

What Happens When Identity Documents Are Stolen at Scale?

The Verge’s in­ves­ti­ga­tion did not iden­tify a spe­cific at­tack or breach. No hacker broke in. No ran­somware gang de­manded pay­ment. The doc­u­ments were sim­ply left there, ac­ces­si­ble by de­sign—or more ac­cu­rately, by de­fault. This is a cat­e­gory of ex­po­sure that se­cu­rity re­searchers call misconfiguration,” but that term ob­scures the re­al­ity: a com­pany han­dling mil­lions of iden­tity doc­u­ments treated them with less care than most peo­ple give to a pub­lic photo al­bum.

Research pub­lished in PMCs cy­ber­se­cu­rity analy­sis demon­strates that the health­care sec­tor con­tin­ues to suf­fer some of the high­est costs from data se­cu­rity breaches, with iden­tity doc­u­ment ex­po­sure cre­at­ing par­tic­u­larly se­vere long-term risks for af­fected in­di­vid­u­als.

The time­line of dis­cov­ery and re­me­di­a­tion re­mains un­clear from avail­able re­port­ing. The doc­u­ments have since been taken of­fline, but the dam­age win­dow—how long they were ac­ces­si­ble, how many peo­ple or au­to­mated sys­tems may have down­loaded them—is un­known. No of­fi­cial state­ment from Nefos or the cannabis clubs us­ing the plat­form has been cited in re­port­ing.

Why Can’t You Just Change” Your Passport Like a Password?

For in­di­vid­u­als whose doc­u­ments were ex­posed, the im­me­di­ate risk is iden­tity theft. Passport and dri­ver’s li­cense scans in crim­i­nal hands can be used to open ac­counts, ap­ply for credit, or fa­cil­i­tate doc­u­ment fraud. There is no uni­ver­sal change your pass­port” op­tion like re­set­ting a com­pro­mised pass­word. The ex­po­sure is per­ma­nent un­less and un­til those doc­u­ments ex­pire or are reis­sued.

Identity Document Vulnerability: • Unlike pass­words, gov­ern­ment-is­sued IDs can­not be in­stantly changed or re­voked • Document re­place­ment re­quires lengthy bu­reau­cratic processes across mul­ti­ple coun­tries • Criminal use of stolen doc­u­ments can con­tinue for years be­fore de­tec­tion

The broader im­pli­ca­tion is sharper: any com­pany col­lect­ing iden­tity doc­u­ments for ver­i­fi­ca­tion pur­poses is now on no­tice that we’ll just store them se­curely” is not a cred­i­ble promise with­out demon­strated tech­ni­cal con­trols. The NIST Computer Security Incident Handling Guide es­tab­lishes base­line se­cu­rity re­quire­ments that were com­pletely ab­sent in this case—no pass­word pro­tec­tion, no en­cryp­tion, no ac­cess logs.

What re­mains unan­swered is whether reg­u­la­tory bod­ies in the European coun­tries af­fected will im­pose penal­ties on Nefos or the cannabis clubs for this ex­po­sure, and whether in­di­vid­u­als will have any re­course for iden­tity restora­tion or mon­i­tor­ing. The struc­tural par­al­lel to data col­lec­tion fail­ures that de­fined pre­vi­ous pri­vacy scan­dals sug­gests this in­ci­dent rep­re­sents a broader fail­ure in how com­pa­nies ap­proach sen­si­tive data stew­ard­ship. As of mid-April 2026, those ques­tions hang open.

Nearly a million passports and photo IDs were left unprotected on the public internet

www.theverge.com

Typing a few let­ters and num­bers into my web browser, I find my­self gap­ing at the iden­tity doc­u­ments of com­plete strangers. The pass­port of a young woman from Germany. The pass­port of a man from Spain with glasses rest­ing on his head. The front and back of an­other man’s dri­ver’s li­cense, a stereo­typ­i­cally goofy ex­pres­sion on his face.

They were all sit­ting un­pro­tected at pub­lic URLs, with no pass­word or ac­cess con­trol of any sort. If I sent you a link, you could have looked at some­one’s pass­port.

We have to do some­thing about it as fast as pos­si­ble, be­cause peo­ple will find this and re­sell it. It will do dam­age,” Sammy Azdoufal told me in May.

Azdoufal is the se­cu­rity re­searcher who used Claude Code to help dis­cover that every DJI Romo ro­bot vac­uum cleaner and a mil­lion baby mon­i­tors and se­cu­rity cam­eras were em­bar­rass­ingly easy to hack. This time, he says he dis­cov­ered over 985,000 photo IDs sit­ting on the pub­lic in­ter­net for any half-de­cent hacker to steal.

If you’ve vis­ited a cannabis club in Spain, Azdoufal says, chances are your photo ID was among them — and pos­si­bly your phone num­ber, ad­dress, your fa­vorite strains of cannabis, and how much you con­sumed each month while there. Azdoufal says celebri­ties are in the data­base, too, and vis­i­tors from all over the world, in­clud­ing 30,000 from the United States. They have fa­mous peo­ple,” says Azdoufal. People who don’t want every­one to know they smoke weed.”

Here’s a rough sum­mary of the user base that Azdoufal’s au­to­mated tool was able to see and the names of some of the clubs:

Image: Sammy Azdoufal

It’s not the clubs that did­n’t pro­tect these iden­tity doc­u­ments. An Irish com­pany called Cannabis Club Systems (CCS), for­mally Nefos Solutions, de­vel­ops and pro­vides the soft­ware these clubs use for sales, ac­count­ing, and ad­mis­sions, in­clud­ing a ver­i­fi­ca­tion sys­tem where re­cep­tion­ists up­load your IDs and self­ies to Nefos’ cloud.

Traditionally, you’d need to pro­vide a photo ID every time you wanted to get into a club. But with the ver­i­fi­ca­tion sys­tem, the re­cep­tion­ist can pull up your stored iden­tity doc­u­ments and check if your face matches. There’s also an op­tional app called PuffPal that lets clubs scan a QR code for faster en­try.

But when Azdoufal de­com­piled that PuffPal app, he ex­plains in his re­port, he dis­cov­ered that Nefos had no mean­ing­ful level of se­cu­rity. He dis­cov­ered a se­cret key for the Stripe pay­ments plat­form sit­ting in­side the app in plain text. He dis­cov­ered he could pull up any mem­ber’s pro­file just by chang­ing one num­ber. If those pro­files in­cluded their phone num­ber, home ad­dress, pass­port, and weed pref­er­ences, he now had ac­cess to them too.

And then, he dis­cov­ered that those pass­ports, dri­vers li­censes, and photo IDs were stored at pub­lic URLs as sim­ple as this: https://​cc­snubev2.com/​v8/​im­ages/​_{club}/​ID/{​user_id}-front.jpg

Those clubs were up­load­ing 5,000 new photo IDs with these in­se­cure URLs every day, Azdoufal tells me.

He also found an ad­min por­tal ac­ces­si­ble via the pub­lic in­ter­net — and that the cannabis clubs had a triv­ial level of se­cu­rity on their own ac­counts, us­ing pass­words that could the­o­ret­i­cally be cracked in min­utes with a mod­ern GPU. Private chat mes­sages be­tween clubs and mem­bers through the PuffPal app were also vul­ner­a­ble.

The good news: Roughly a month af­ter we reached out to Nefos, the com­pany seems to fi­nally be tak­ing mean­ing­ful ac­tion. The com­pany says it’s shut­ting down its en­tire PuffPal sys­tem and vul­ner­a­ble APIs un­til they can be fixed — in Azdoufal’s lat­est tests on June 10th, pass­port im­ages and per­sonal data seem to be se­cure. Nefos has also in­formed lo­cal au­thor­i­ties and says it will take re­spon­si­bil­ity to make fixes, pay fines, and tell users what hap­pened.

In a phone in­ter­view, Nefos co­founder Andreas Nilsen tells The Verge that he’s in touch with Ireland’s Data Protection Commission (DPC) about the data breach — a fact that DPC spokesper­son Evan O’Leary con­firmed to us by email. We have to com­mu­ni­cate to every­one that was po­ten­tially ex­posed,” Nilsen tells me, say­ing he hopes the DPC can show his com­pany how to do that prop­erly. Nilsen claims there’s cur­rently no ev­i­dence that any out­sider ac­cessed the data other than Azdoufal.

But it took far too long for Nefos to take the threat se­ri­ously. It took five days and the threat of a story be­fore the com­pany replied to us, long af­ter Azdoufal reached out. Then, Nefos be­gan by pa­per­ing over the holes in­stead of risk­ing busi­ness.

I was pre­pared to write this story at the be­gin­ning of June, af­ter Azdoufal told me Nefos had fi­nally locked down the pass­port im­ages. But on June 4th, I sur­prised Azdoufal by show­ing him that his very own pass­port was on­line once again, with­out any pro­tec­tion.

That’s be­cause Nefos had not yet stopped cannabis clubs from us­ing the PuffPal app, and clubs were com­plain­ing the locked-down im­ages weren’t show­ing up the way they used to — so Nefos sim­ply un­locked the im­ages again. While Nilsen claims the im­ages were locked down 70 per­cent of the time” since Azdoufal and I got in touch, it’s pretty clear that Nefos made a de­ci­sion to pri­or­i­tize its cus­tomers in­stead of the threat.

On June 9th, Azdoufal dis­cov­ered that even though Nefos had locked down the pass­port im­ages and photo IDs with to­kens, every­thing else in the user pro­files was still eas­ily ac­ces­si­ble: pass­port num­bers, phone num­bers, email ad­dresses, home ad­dresses, every­thing.

All a hacker had to do was type curl -X POST https://​cc­snubev2.com/​v8/​api/​user­Pro­file.php -d user_id=[NUMBER]&[CLUB NAME]=test&language=en” into a com­mand line, and the servers would freely give up a ream of per­sonal in­for­ma­tion. After we brought this to Nefos’ at­ten­tion, that hole, too, has been closed.

But how could the com­pany be so care­less? I don’t want to put the blame on oth­ers be­cause at the end of the day it re­sides with us,” Nilsen says. But he does point the fin­ger at 9Series, an out­sourc­ing firm he claims was re­spon­si­ble for de­vel­op­ing the PuffPal app and cre­at­ing all the vul­ner­a­ble APIs it used to pull un­pro­tected data from Nefos’ user data­base. (9Series did not have a re­sponse by pub­lish time.)

Now that PuffPal is down, Nefos is email­ing every club to let them know their mem­bers won’t be able to use those QR codes for en­try — but they can still pull up IDs from Nefos’ servers af­ter scan­ning a mem­ber’s RFID card or typ­ing in their phone num­ber, among other ex­am­ples.

Nilsen claims his com­pany will not sim­ply re­launch un­se­cured PuffPal if the clubs ask. We’re go­ing to tell them we can’t,” he says. We will make sure, af­ter this de­ba­cle, that this is ver­i­fied by an in­de­pen­dent se­cu­rity re­searcher and guar­an­tee that this is 100 per­cent se­cure.” He says Nefos is part­ing ways with 9Series and hopes to have a new app within a few months.

Nilsen says he’s aware that un­der EU law, his com­pany legally had to dis­close the breach within 72 hours or pay sig­nif­i­cant fines, some­thing the com­pany did­n’t do. I’m sure we’ll get what­ever kind of penalty there is,” Nilsen says.

Just last month, a web­site called the UK Visa Portal sim­i­larly ex­posed at least 100,000 pass­ports to any­one who could guess a URL. Let’s hope this is a wakeup call.

Follow top­ics and au­thors from this story to see more like this in your per­son­al­ized home­page feed and to re­ceive email up­dates.

Sean Hollister

GitHub - deepreinforce-ai/Ornith-1

github.com

Aloha! 🌺 Ornith-1.0 is a self-im­prov­ing open-source mod­els for agen­tic cod­ing.

Highlights:

State-of-the-Art Coding Agents: Available in 9B-Dense, 31B-Dense, 35B-MoE, and 397B-MoE (post-trained on top of Gemma 4 and Qwen 3.5), achiev­ing state-of-the-art per­for­mance among open-source mod­els of com­pa­ra­ble size on cod­ing bench­marks such as Terminal-Bench 2.1, SWE-Bench, NL2Repo and OpenClaw.

Self-Improving Training Framework: Ornith-1.0 em­ploys RL to learn to gen­er­ate not only so­lu­tion roll­outs, but also the scall­fold that drive those roll­outs. By jointly op­ti­miz­ing the scaf­fold and the re­sult­ing so­lu­tion, the model dis­cov­ers bet­ter search tra­jec­to­ries and gen­er­ates higher-qual­ity so­lu­tions.

Licence: MIT li­censed, glob­ally ac­ces­si­ble, and free from re­gional lim­i­ta­tions.

Benchmarks

Each model is eval­u­ated against its size-ap­pro­pri­ate base­lines. All three use the same har­nesses and de­cod­ing setup (see the notes un­der the ta­bles).

Ornith-1.0 – 9B

Ornith-1.0 – 35B

Ornith-1.0 – 397B

* Terminal-Bench 2.1 (Terminus-2): eval­u­ated with the Harbor/Terminus-2 frame­work, parser=json, tem­per­a­ture=1.0, top_p=1.0, 128K con­text win­dow. Each run uses a 4-hour time­out with 32 CPU cores and 48GB RAM, av­er­aged over 5 runs. We ad­just the Qwen chat tem­plate to keep train­ing and in­fer­ence con­sis­tent and mod­ify Harbor to align with vLLM’s rea­son­ing_­con­tent key. * Terminal-Bench 2.1 (Claude Code): eval­u­ated with Claude Code 2.1.126, parser=json, tem­per­a­ture=1.0, top_p=1.0, max_new_­to­kens=131072, av­er­aged over 5 runs (Qwen chat tem­plate like­wise mod­i­fied). * SWE-bench Verified / Pro / Multilingual: OpenHands har­ness, temp=1.0, top_p=0.95, 256K con­text win­dow. * SWE Atlas QnA / RF / TW: mini-SWE-agent har­ness, temp=1.0, top_p=0.95, 128K con­text win­dow, av­er­aged over 5 runs. * NL2Repo: tem­per­a­ture=1.0, top_p=1.0, 400K con­text, 48K out­put, anti-hack­ing fil­ters. * ClawEval: an agen­tic code bench­mark over real-user task dis­tri­b­u­tions; temp=0.6, 256K con­text.

Quickstart

NOTE Ornith-1.0 is a rea­son­ing model: by de­fault the as­sis­tant turn opens with a <think> … </think> block be­fore the fi­nal an­swer. The serv­ing recipes be­low en­able a rea­son­ing parser so the chain-of-thought is re­turned in a sep­a­rate rea­son­ing_­con­tent field, and a tool-call parser so the mod­el’s <tool_call> blocks are sur­faced as OpenAI-style tool_­calls. Serving Ornith-1.0 re­quires re­cent run­times:

Transformers ≥ 5.8.1 vLLM ≥ 0.19.1 SGLang ≥ 0.5.9

Recommended sam­pling pa­ra­me­ters: tem­per­a­ture=0.6, top_p=0.95, top_k=20 (use tem­per­a­ture=1.0 to re­pro­duce the re­ported bench­mark setup).

NOTE

Ornith-1.0 is a rea­son­ing model: by de­fault the as­sis­tant turn opens with a <think> … </think> block be­fore the fi­nal an­swer. The serv­ing recipes be­low en­able a rea­son­ing parser so the chain-of-thought is re­turned in a sep­a­rate rea­son­ing_­con­tent field, and a tool-call parser so the mod­el’s <tool_call> blocks are sur­faced as OpenAI-style tool_­calls.

Serving Ornith-1.0 re­quires re­cent run­times:

Transformers ≥ 5.8.1

vLLM ≥ 0.19.1

SGLang ≥ 0.5.9

Recommended sam­pling pa­ra­me­ters: tem­per­a­ture=0.6, top_p=0.95, top_k=20 (use tem­per­a­ture=1.0 to re­pro­duce the re­ported bench­mark setup).

Serving Ornith-1.0

Ornith-1.0 ships as a dense 9B model plus two Mixture-of-Experts mod­els (35B, 397B). All check­points ex­pose the same OpenAI-compatible in­ter­face and sup­port a 256K (262,144-token) con­text win­dow; the dense 9B fits on a sin­gle 80GB GPU, while the MoE check­points are sharded across a multi-GPU node with ten­sor par­al­lelism. Each size is pub­lished in mul­ti­ple pre­ci­sion / for­mat vari­ants:

The recipes be­low stand up an OpenAI-compatible server un­der the shared alias Ornith-1.0. Set MODEL to the check­point you want, and match –tensor-parallel-size / –tp to your GPU count.

vLLM

# Pick a check­point — dense 9B, or MoE 35B / 397B (append -FP8 for lower-VRAM serv­ing): MODEL=deepreinforce-ai/Ornith-1.0 – 397B

# MoE check­points (35B / 397B): shard across the node with ten­sor par­al­lelism. # Dense check­point (9B): fits on a sin­gle 80GB GPU — drop –tensor-parallel-size. vllm serve $MODEL \ –served-model-name Ornith-1.0 \ –tensor-parallel-size 8 \ –host 0.0.0.0 –port 8000 \ –max-model-len 262144 \ –gpu-memory-utilization 0.90 \ –enable-prefix-caching \ –enable-auto-tool-choice –tool-call-parser qwen3_xml \ –reasoning-parser qwen3 \ –trust-remote-code

SGLang

# Pick a check­point — dense 9B, or MoE 35B / 397B (append -FP8 for lower-VRAM serv­ing): MODEL=deepreinforce-ai/Ornith-1.0 – 397B

# MoE check­points (35B / 397B): shard with –tp ; dense 9B: drop –tp for a sin­gle GPU. python -m sglang.launch_server \ –model-path $MODEL \ –served-model-name Ornith-1.0 \ –tp 8 \ –host 0.0.0.0 –port 8000 \ –context-length 262144 \ –mem-fraction-static 0.85 \ –tool-call-parser qwen3_­coder \ –reasoning-parser qwen3

Hugging Face Transformers

For a quick lo­cal test (or to script of­fline gen­er­a­tion), load the model di­rectly with Transformers. Make sure you have a re­cent re­lease in­stalled — see the Transformers in­stal­la­tion guide; Ornith-1.0 re­quires trans­form­ers >= 5.8.1. The dense 9B check­point is the eas­i­est to run lo­cally.

from trans­form­ers im­port AutoModelForCausalLM, AutoTokenizer

mod­el_­name = deepreinforce-ai/Ornith-1.0 – 9B” # or -35B / -397B

to­k­enizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained( mod­el_­name, dtype=“auto”, de­vice_map=“auto”, )

mes­sages = [ {“role”: user”, content”: Write a Python func­tion is_prime(n). Keep it short.“} ] text = to­k­enizer.ap­ply_chat_tem­plate( mes­sages, to­k­enize=False, ad­d_­gen­er­a­tion_prompt=True, )

in­puts = to­k­enizer(text, re­turn_ten­sors=“pt”).to(model.de­vice) gen­er­ated = model.gen­er­ate( **inputs, max_new_­to­kens=512, do_sam­ple=True, tem­per­a­ture=0.6, top_p=0.95, top_k=20, ) out­put_ids = gen­er­ated[0][in­puts.in­put_ids.shape[1]:]

# The re­ply con­tains a <think> … </think> rea­son­ing block fol­lowed by the an­swer. con­tent = to­k­enizer.de­code(out­put_ids, skip_spe­cial_­to­kens=True) print(con­tent)

To split the rea­son­ing trace from the fi­nal an­swer, parse on the </think> marker:

text = to­k­enizer.de­code(out­put_ids, skip_spe­cial_­to­kens=True) if </think>” in text: rea­son­ing, an­swer = text.split(“</​think>”, 1) rea­son­ing = rea­son­ing.re­place(“<think>”, ”).strip() an­swer = an­swer.strip() else: rea­son­ing, an­swer = ”, text.strip()

Using Ornith-1.0 via the Chat Completions API

Once a vLLM or SGLang server is run­ning, talk to it with any OpenAI-compatible client.

Basic Usage

from ope­nai im­port OpenAI

client = OpenAI( base_url=“http://​lo­cal­host:8000/​v1, api_key=“EMPTY”, # any non-empty string works for a lo­cal server )

re­sponse = client.chat.com­ple­tions.cre­ate( model=“Or­nith-1.0”, mes­sages=[ {“role”: user”, content”: Write a one-line Python lambda that squares a num­ber.“} ], tem­per­a­ture=0.6, top_p=0.95, max_­to­kens=1024, )

mes­sage = re­sponse.choices[0].mes­sage # rea­son­ing_­con­tent holds the <think> trace; con­tent holds the fi­nal an­swer. print(“rea­son­ing:”, getattr(mes­sage, reasoning_content”, None)) print(“an­swer:”, mes­sage.con­tent)

You can also stream to­kens, or hand the model tools — Ornith-1.0 emits well-formed func­tion calls that the server parses into the stan­dard tool_­calls field:

tools = [ { type”: function”, function”: { name”: get_weather”, description”: Get the cur­rent weather for a city”, parameters”: { type”: object”, properties”: {“city”: {“type”: string”}}, required”: [“city”], }, }, } ]

re­sponse = client.chat.com­ple­tions.cre­ate( model=“Or­nith-1.0”, mes­sages=[{“role”: user”, content”: What is the weather in Paris right now?“}], tools=tools, tool_­choice=“auto”, tem­per­a­ture=0.6, max_­to­kens=2048, )

tool_­call = re­sponse.choices[0].mes­sage.tool_­calls[0] print(tool_­call.func­tion.name, tool_­call.func­tion.ar­gu­ments) # -> get_weather {“city”: Paris”}

You can point any OpenAI-compatible SDK (Python, Node.js, etc.) or curl at the same /v1/chat/completions end­point.

Agentic Usage

Ornith-1.0 ex­cels in tool-call­ing and agen­tic cod­ing ca­pa­bil­i­ties.

Agent Frameworks

Because Ornith-1.0 ex­poses an OpenAI-compatible end­point with tool call­ing, it works out of the box with stan­dard agent frame­works. Below is a min­i­mal ex­am­ple that con­nects Ornith-1.0 to tools through an MCP server.

im­port os from ope­nai im­port OpenAI

client = OpenAI( base_url=os.getenv(“OPE­NAI_BASE_URL”, http://​lo­cal­host:8000/​v1), api_key=os.getenv(“OPE­NAI_API_KEY”, EMPTY), )

tools = [ { type”: function”, function”: { name”: run_shell”, description”: Run a shell com­mand and re­turn its out­put.”, parameters”: { type”: object”, properties”: { command”: {“type”: string”, description”: The com­mand to run”} }, required”: [“command”], }, }, } ]

mes­sages = [{“role”: user”, content”: List the Python files in the cur­rent di­rec­tory.“}]

re­sponse = client.chat.com­ple­tions.cre­ate( model=“Or­nith-1.0”, mes­sages=mes­sages, tools=tools, tem­per­a­ture=0.6, top_p=0.95, ) print(re­sponse.choices[0].mes­sage)

Examples of us­ing Ornith with agent har­ness:

Hermes Agent

# Hermes talks to any OpenAI-compatible end­point — point it at your Ornith server. ex­port OPENAI_BASE_URL=“http://​lo­cal­host:8000/​v1 ex­port OPENAI_API_KEY=“EMPTY” ex­port MODEL=“Ornith-1.0”

OpenHands

pip in­stall open­hands-ai

# OpenHands routes through LiteLLM; the openai/” pre­fix se­lects the OpenAI-compatible path. ex­port LLM_MODEL=“openai/Ornith-1.0″ ex­port LLM_BASE_URL=“http://​lo­cal­host:8000/​v1 ex­port LLM_API_KEY=“EMPTY”

# Launch the CLI (or run the of­fi­cial OpenHands Docker im­age with the same env vars). open­hands

llama.cpp / Ollama

# Both run­times load a GGUF build — avail­able for the 9B and 35B check­points (swap -9B for -35B).

# llama.cpp — serve an OpenAI-compatible API on port 8000. llama-server -hf deep­re­in­force-ai/​Or­nith-1.0 – 9B-GGUF –port 8000 -c 262144

# Ollama — pull and chat with the same GGUF straight from Hugging Face. ol­lama run hf.co/​deep­re­in­force-ai/​Or­nith-1.0 – 9B-GGUF

Unsloth Studio

pip in­stall un­sloth

# Load Ornith for fast lo­cal in­fer­ence or fine-tun­ing (Python): # from un­sloth im­port FastLanguageModel # model, to­k­enizer = FastLanguageModel.from_pretrained( # deepreinforce-ai/Ornith-1.0 – 9B”, # max_se­q_length=262144, # load­_in­_4bit=True, # )

OpenClaw

# OpenClaw talks to any OpenAI-compatible end­point — point it at your Ornith server. ex­port OPENAI_BASE_URL=“http://​lo­cal­host:8000/​v1 ex­port OPENAI_API_KEY=“EMPTY” ex­port OPENAI_MODEL=“Ornith-1.0”

Coding CLIs

Ornith-1.0 is op­ti­mized for ter­mi­nal-based cod­ing agents. Point any OpenAI-compatible cod­ing CLI at your Ornith-1.0 end­point (set OPENAI_BASE_URL and OPENAI_API_KEY) to un­der­stand large code­bases, au­to­mate te­dious work, and ship faster.

OpenCode

# Register your lo­cal Ornith end­point as a provider in ~/.config/opencode/opencode.json: # # { # $schema”: https://​open­code.ai/​con­fig.json, # provider”: { # ornith”: { # npm”: @ai-sdk/openai-compatible”, # name”: Ornith (local)”, # options”: { baseURL”: http://​lo­cal­host:8000/​v1, apiKey”: EMPTY }, # models”: { Ornith-1.0”: { name”: Ornith-1.0” } } # } # } # }

open­code

Citation

If you find our work help­ful, feel free to give us a cite.

@misc{ornith-1.0, ti­tle = {{Ornith-1.0}: Agentic Coding, Open to All}, url = {https://​deep-re­in­force.com/​or­nith_1_0.html}, au­thor = {{DeepReinforce Team}}, year = {2026} }

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

Visit pancik.com for more.