10 interesting stories served every morning and every evening.




1 641 shares, 35 trendiness

Europeans’ health data sold to U.S. firm run by ex-Israeli spies

You’re only see­ing part of our work. Create an ac­count to ex­plore all our in­ves­ti­ga­tions. Try it for free for 30 days, no strings at­tached.

You’re only see­ing part of our work. Create an ac­count to ex­plore all our in­ves­ti­ga­tions. Try it for free for 30 days, no strings at­tached.

The European mes­sag­ing ser­vice Zivver — which is used for con­fi­den­tial com­mu­ni­ca­tion by gov­ern­ments and hos­pi­tals in the EU and the U. K. — has been sold to Kiteworks, an American com­pany with strong links to Israeli in­tel­li­gence. Experts have ex­pressed deep con­cerns over the deal.

With the sale of Amsterdam-based data se­cu­rity com­pany Zivver, sen­si­tive in­for­ma­tion about European cit­i­zens is now in the hands of Kiteworks. The CEO of the American tech com­pany is a for­mer cy­ber spe­cial­ist from an elite unit of the Israeli army, as are sev­eral other mem­bers of its top man­age­ment. Var­i­ous in­sti­tu­tions in Europe and the U. K. — from hos­pi­tals to courts and im­mi­gra­tion ser­vices — use Zivver to send con­fi­den­tial doc­u­ments. While Zivver says these doc­u­ments are en­crypted, an in­ves­ti­ga­tion by Follow the Money shows that the com­pany is able to read their con­tents.Why does this mat­ter?Cy­ber­se­cu­rity and in­tel­li­gence ex­perts told Follow the Money that the takeover should ei­ther have been pre­vented or prop­erly as­sessed in ad­vance. Zivver processes in­for­ma­tion that could be ex­tremely valu­able to third par­ties, such as crim­i­nals or for­eign in­tel­li­gence ser­vices. That in­for­ma­tion is now sub­ject to in­va­sive U.S. law, and over­seen by a com­pany with well-doc­u­mented links to Israeli in­tel­li­gence.How was this in­ves­ti­gated?Fol­low the Money in­ves­ti­gated the ac­qui­si­tion of Zivver and the man­age­ment of Kiteworks, and spoke to ex­perts in in­tel­li­gence ser­vices and cy­ber se­cu­rity.

This ar­ti­cle is part of an on­go­ing se­ries.

When the American data se­cu­rity com­pany Kiteworks bought out its Dutch in­dus­try peer Zivver in June, CEO Jonathan Yaron de­scribed it as a proud mo­ment for all of us”. The pur­chase was a sig­nif­i­cant mile­stone in Kiteworks’ con­tin­ued mis­sion to safe­guard sen­si­tive data across all com­mu­ni­ca­tion chan­nels”, he added in a LinkedIn post. But what Yaron did not men­tion was that this ac­qui­si­tion — com­ing at a po­lit­i­cally charged mo­ment be­tween the U.S. and the EU — put highly sen­si­tive, per­sonal data be­long­ing to European and British cit­i­zens di­rectly into American hands. Zivver is used by in­sti­tu­tions in­clud­ing hos­pi­tals, health in­sur­ers, gov­ern­ment ser­vices and im­mi­gra­tion au­thor­i­ties in coun­tries in­clud­ing the Netherlands, Germany, Belgium and the U.K.Neither did Yaron men­tion that much of Kiteworks’ top man­age­ment — him­self in­cluded — are for­mer mem­bers of an elite Israeli Defence Force unit that spe­cialised in eaves­drop­ping and break­ing en­crypted com­mu­ni­ca­tions.

Our jour­nal­ism is only pos­si­ble thanks to the trust of our pay­ing mem­bers. Not a mem­ber yet? Sign up now

In ad­di­tion to this, an in­ves­ti­ga­tion by Follow the Money shows that data processed by Zivver is less se­cure than the ser­vice leads its cus­tomers to be­lieve. Research found that emails and doc­u­ments sent by Zivver can be read by the com­pany it­self. This was later con­firmed by Zivver to Follow the Money.“All of the red flags should have been raised dur­ing this ac­qui­si­tion”Zivver main­tained, how­ever, that it does not have ac­cess to the en­cryp­tion keys used by cus­tomers, and there­fore can­not hand over data to U.S. au­thor­i­ties. This is de­spite in­de­pen­dent re­searchers con­firm­ing that the data was — for a brief pe­riod — ac­ces­si­ble to the com­pany. If U.S. of­fi­cials wanted ac­cess to such com­mu­ni­ca­tion, Zivver would be legally ob­lig­ated to pro­vide it.Cy­ber­se­cu­rity ex­perts now point to se­ri­ous se­cu­rity con­cerns, and ask why this sale seems to have gone through with­out scrutiny from European au­thor­i­ties.“All of the red flags should have been raised dur­ing this ac­qui­si­tion,” said in­tel­li­gence ex­pert Hugo Vijver, a for­mer long-term of­fi­cer in AIVD, the Dutch se­cu­rity ser­vice.Am­s­ter­dam-based Zivver — which was founded in 2015 by Wouter Klinkhamer and Rick Goud — pro­vides sys­tems for the en­crypted ex­change of in­for­ma­tion via email, chat and video, among other means. Dutch courts, for ex­am­ple, work with Zivver to send clas­si­fied doc­u­ments, and so­lic­i­tors use the ser­vice to send con­fi­den­tial in­for­ma­tion to the courts. Other gov­ern­ment agen­cies in the Netherlands — in­clud­ing also use Zivver. So do vi­tal in­fra­struc­ture op­er­a­tors such as the Port of Rotterdam and The Hague Airport.

In the U.K., a num­ber of NHS hos­pi­tals and lo­cal coun­cils In it is used in ma­jor hos­pi­tals. The in­for­ma­tion that Zivver se­cures for its cus­tomers is there­fore con­fi­den­tial and sen­si­tive by na­ture. When ap­proached by Follow the Money, a num­ber of gov­ern­men­tal agen­cies said the com­pa­ny’s Dutch ori­gins were a big fac­tor in their de­ci­sion to use Zivver. Additionally, the fact that the data trans­ferred via Zivver was stored on servers in Europe also played a role in their de­ci­sions. Now that Zivver has been ac­quired by a com­pany in the United States, that data is This means that the U.S. gov­ern­ment can re­quest ac­cess to this in­for­ma­tion if it wishes, re­gard­less of where the data is stored.These laws are not new, but they have be­come even more dra­con­ian since U.S. President Donald Trump’s re­turn to of­fice, ac­cord­ing to ex­perts.Bert Hubert, a for­mer reg­u­la­tor of the Dutch in­tel­li­gence ser­vices, warned: America is de­te­ri­o­rat­ing so rapidly, both legally and de­mo­c­ra­t­i­cally, that it would be very naive to hand over your courts and hos­pi­tals to their ser­vices.” “Trump re­cently called on Big Tech to ig­nore European leg­is­la­tion. And that is what they are go­ing to do. We have no con­trol over it,” he added.

In Europe, Hubert said: We com­mu­ni­cate al­most ex­clu­sively via American plat­forms. And that means that the U.S. can read our com­mu­ni­ca­tions and dis­rupt our en­tire so­ci­ety if they de­cide that they no longer like us.”Zivver had of­fered an al­ter­na­tive — a European plat­form gov­erned by EU law. “We are now throw­ing that away. If you want to share some­thing con­fi­den­tial with a court or gov­ern­ment, con­sider us­ing a type­writer. That’s about all we have left,” Hubert said.Be­yond American ju­ris­dic­tion, Kiteworks’ man­age­ment raises an­other layer of con­cern: its links to Israeli in­tel­li­gence.Sev­eral of the com­pa­ny’s top ex­ec­u­tives, in­clud­ing CEO Yaron, are vet­er­ans of Unit 8200, the elite cy­ber unit of the Israel Defence Force (IDF). The unit is renowned for its code-break­ing abil­i­ties and feared for its sur­veil­lance op­er­a­tions.

In Israel, there is a re­volv­ing door be­tween the army, lobby, busi­ness and pol­i­tics

Unit 8200 has been linked to ma­jor cy­ber op­er­a­tions, in­clud­ing the Stuxnet at­tack on Iranian nu­clear fa­cil­i­ties in 2007. More re­cently, it was ac­cused of or­ches­trat­ing the det­o­na­tion of thou­sands of pagers in Lebanon, an in­ci­dent the United Nations said vi­o­lated in­ter­na­tional law and killed at least two chil­dren.The unit em­ploys thou­sands of young re­cruits iden­ti­fied for their dig­i­tal skills. It is able to in­ter­cept global tele­phone and in­ter­net traf­fic.In­ter­na­tional me­dia have re­ported that Unit 8200 in­ter­cepts and stores an av­er­age of one mil­lion Palestinian phone calls every hour, data that ends up on Some vet­er­ans them­selves have also ob­jected to the work of the unit. In 2014, dozens of re­servists signed a let­ter to Israeli lead­ers say­ing they no longer wanted to par­tic­i­pate in sur­veil­lance of the oc­cu­pied ter­ri­to­ries.“The lines of com­mu­ni­ca­tion be­tween the Israeli de­fence ap­pa­ra­tus and the busi­ness com­mu­nity have tra­di­tion­ally been very short,” said Dutch in­tel­li­gence ex­pert Vijver. In Israel, there is a re­volv­ing door be­tween the army, lobby, busi­ness and pol­i­tics.”That re­volv­ing door is clearly vis­i­ble in big U.S. tech com­pa­nies — and Kiteworks is no ex­cep­tion.Aside from Yaron, both Chief Business Officer Yaron Galant and Chief Product Officer served in Unit 8200, ac­cord­ing to pub­licly avail­able in­for­ma­tion.They played a di­rect role in ne­go­ti­at­ing the ac­qui­si­tion of Zivver. Their back­ground was known to Zivver’s di­rec­tors Goud and Klinkhamer at the time.

What is tran­spir­ing within the European Union? What are the goals and as­pi­ra­tions of the EU, and how is the bud­get al­lo­cated?

Other se­nior fig­ures also have mil­i­tary in­tel­li­gence back­grounds. Product di­rec­tor Ron Margalit worked in Unit 8200 be­fore serv­ing in the of­fice of Israeli Prime Minister Benjamin Netanyahu. Mergers and ac­qui­si­tions di­rec­tor Uri Kedem is a for­mer Israeli naval cap­tain.Kite­works is not unique in this re­spect. In­creas­ing num­bers of U.S. cy­ber­se­cu­rity firms now em­ploy for­mer Israeli in­tel­li­gence of­fi­cers. This trend, ex­perts say, cre­ates vul­ner­a­bil­i­ties that are rarely dis­cussed.An in­de­pen­dent re­searcher quoted by U.S. Drop Site News said: Not all of these vet­er­ans will send clas­si­fied data to Tel Aviv. But the fact that so many for­mer spies work for these com­pa­nies does cre­ate a se­ri­ous vul­ner­a­bil­ity: no other coun­try has such ac­cess to the Or, as the ex-in­tel­li­gence reg­u­la­tor Hubert put it: Gaining ac­cess to com­mu­ni­ca­tion flows is part of Israel’s long-term strat­egy. A com­pany like Zivver fits per­fectly into that strat­egy.”The in­for­ma­tion han­dled by Zivver — con­fi­den­tial com­mu­ni­ca­tions be­tween gov­ern­ments, hos­pi­tals and cit­i­zens — is a po­ten­tial gold­mine for in­tel­li­gence ser­vices.Ac­cord­ing to in­tel­li­gence ex­pert Vijver, ac­cess to this kind of ma­te­r­ial makes it eas­ier to pres­sure in­di­vid­u­als into co­op­er­at­ing with in­tel­li­gence agen­cies. Once an in­tel­li­gence ser­vice has ac­cess to med­ical, fi­nan­cial and per­sonal data, it can more eas­ily pres­sure peo­ple into spy­ing for it, he said.But the gain for in­tel­li­gence ser­vices lies not just in sen­si­tive in­for­ma­tion, said Hubert: Any data that al­lows an agency to tie tele­phone num­bers, ad­dresses or pay­ment data to an in­di­vid­ual is of great in­ter­est to them.” He added: It is ex­actly this type of data that is abun­dantly pre­sent in com­mu­ni­ca­tions be­tween civil­ians, gov­ern­ments and care in­sti­tu­tions. In other words, the in­for­ma­tion that flows through a com­pany like Zivver is ex­tremely valu­able for in­tel­li­gence ser­vices.”These geopo­lit­i­cal con­cerns be­come more pro­nounced when com­bined with tech­ni­cal wor­ries about Zivver’s en­cryp­tion. For years, Zivver pre­sented it­self as a European al­ter­na­tive that guar­an­teed pri­vacy. Its mar­ket­ing ma­te­ri­als claimed that mes­sages were en­crypted on the sender’s de­vice and that the com­pany had zero ac­cess” to con­tent. But an in­ves­ti­ga­tion by two cy­ber­se­cu­rity ex­perts at a Dutch gov­ern­ment agency, at the re­quest of Follow the Money, un­der­mines this claim.

The ex­perts, who par­tic­i­pated in the in­ves­ti­ga­tion on con­di­tion of anonymity, ex­plored what hap­pened when that gov­ern­ment agency logged into Zivver’s web ap­pli­ca­tion to send in­for­ma­tion.Tests showed that when gov­ern­ment users sent mes­sages through Zivver’s web ap­pli­ca­tion, the con­tent — in­clud­ing at­tach­ments — was up­loaded to Zivver’s servers as read­able text be­fore be­ing en­crypted. The same process ap­plied to email ad­dresses of senders and re­cip­i­ents.“In these spe­cific cases, Zivver processed the mes­sages in read­able form,” said in­de­pen­dent cy­ber­se­cu­rity re­searcher Matthijs Koot, who ver­i­fied the find­ings. “Even if only briefly, tech­ni­cally speak­ing it is pos­si­ble that Zivver was able to view these mes­sages,” he said.He added: Whether a mes­sage is en­crypted at a later stage makes lit­tle dif­fer­ence. It may help against hack­ers, but it no longer mat­ters in terms of pro­tec­tion against Zivver.”Despite these find­ings, Zivver con­tin­ues to in­sist on its web­site and in pro­mo­tional ma­te­r­ial else­where — in­clud­ing on the U.K. gov­ern­men­t’s Digital Marketplace — that contents of se­cure mes­sages are in­ac­ces­si­ble to Zivver and third par­ties”.So far, no ev­i­dence has sur­faced that Zivver mis­used its tech­ni­cal ac­cess. But now that the com­pany is owned by Kiteworks, ex­perts see a height­ened risk.For­mer in­tel­li­gence of­fi­cer Vijver puts it bluntly: Given the links be­tween Zivver, Kiteworks and Unit 8200, I be­lieve there is zero chance that no data is go­ing to Israel. To think oth­er­wise is com­pletely naive.”The sale of Zivver could tech­ni­cally have been blocked or in­ves­ti­gated un­der Dutch law. According to the Security Assessment of Investments, Mergers and Acquisitions Act, such sen­si­tive takeovers are sup­posed to be re­viewed by a spe­cialised agency. But the Dutch in­te­rior min­istry de­clared that Zivver was not part of the coun­try’s critical in­fra­struc­ture,” mean­ing that no re­view was car­ried out.That, in Hubert’s view, was a huge blun­der”.

It’s bad enough that a com­pany that plays such an im­por­tant role in gov­ern­ment com­mu­ni­ca­tions is falling into American hands, but the fact that there are all kinds of Israeli spies there is very se­ri­ous,” he said.“The takeover is tak­ing place in an un­safe world full of geopo­lit­i­cal ten­sions”Ex­perts say the Zivver case high­lights Europe’s lack of strate­gic con­trol over its dig­i­tal in­fra­struc­ture.Mar­iëtte van Huijstee of the Netherlands-based said: I doubt whether the se­cu­rity of sen­si­tive emails and files … should be left to the pri­vate sec­tor. And if you think that is ac­cept­able, should we leave it to non-Eu­ro­pean par­ties over whom we have no con­trol?”“We need to think much more strate­gi­cally about our dig­i­tal in­fra­struc­ture and reg­u­late these kinds of is­sues much bet­ter, for ex­am­ple by des­ig­nat­ing en­cryp­tion ser­vices as vi­tal in­fra­struc­ture,” she added.Zivver, for its part, claimed that se­cu­rity will im­prove un­der Kiteworks. Zivver’s full re­sponses to Follow the Money’s ques­tions can be read here and here.But Van Huijstee was not con­vinced.“Kite­works em­ploys peo­ple who come from a ser­vice that spe­cialises in de­crypt­ing files,” she said. “The takeover is tak­ing place in an un­safe world full of geopo­lit­i­cal ten­sions, and we are deal­ing with data that is very valu­able. In such a case, trust is not enough and more con­trol is needed.”

...

Read the original on www.ftm.eu »

2 291 shares, 22 trendiness

A Plain-Text Spaced Repetition System

hash­cards is a lo­cal-first spaced rep­e­ti­tion app, along the lines of

Anki or Mochi. Like Anki, it uses FSRS, the most ad­vanced sched­ul­ing al­go­rithm yet, to sched­ule re­views.

The thing that makes hash­cards unique: it does­n’t use a data­base. Rather, your flash­card col­lec­tion is just a di­rec­tory of Markdown files, like so:

And each file, or deck”, looks like this:

Q: What is the role of synap­tic vesi­cles?

A: They store neu­ro­trans­mit­ters for re­lease at the synap­tic ter­mi­nal.

Q: What is a neu­rite?

A: A pro­jec­tion from a neu­ron: ei­ther an axon or a den­drite.

C: Speech is [produced] in [Broca’s] area.

C: Speech is [understood] in [Wernicke’s] area.

You write flash­cards more or less like you’d write or­di­nary notes, with light­weight markup to de­note ba­sic (question/answer) flash­cards and cloze

dele­tion flash­cards. Then, to study, you run:

This opens a web in­ter­face on lo­cal­host:8000, where you can re­view the flash­cards. Your per­for­mance and re­view his­tory is stored in an SQLite

data­base in the same di­rec­tory as the cards. Cards are con­tent-ad­dressed, that is, iden­ti­fied by the hash of their text.

This cen­tral de­sign de­ci­sion yields many ben­e­fits: you can edit your flash­cards with your ed­i­tor of choice, store your flash­card col­lec­tion in a Git repo, track its changes, share it on GitHub with oth­ers (as I have). You can use scripts to gen­er­ate flash­cards from some source of struc­tured data (e.g. a CSV of English/French vo­cab­u­lary pairs). You can query and ma­nip­u­late your col­lec­tion us­ing stan­dard Unix tools, or pro­gram­mat­i­cally, with­out hav­ing to dig into the in­ter­nals of some ap­p’s data­base.

Why build a new spaced rep­e­ti­tion app? Mostly be­cause I was dis­sat­is­fied with both Anki and Mochi. But also, ad­di­tion­ally, be­cause my flash­cards col­lec­tion is very im­por­tant to me, and hav­ing it ex­ist ei­ther in some re­mote data­base, or as an opaque un­us­able data blob on my com­puter, does­n’t feel good. Markdown files in a Git repo” gives me a level of own­er­ship that other ap­proaches lack.

The rest of this post ex­plains my frus­tra­tions with Anki and Mochi, and how I landed on the de­sign de­ci­sions for hash­cards.

Anki was the first SR sys­tem I used. It’s open source, so it will be around for­ever; it has a mil­lion plu­g­ins; it was the first SR sys­tem to use FSRS for sched­ul­ing. It has re­ally rich stats, which I think are mostly use­less but are fun to look at. And the note types fea­ture is re­ally good: it lets you gen­er­ate a large num­ber of flash­cards au­to­mat­i­cally from struc­tured data.

The cen­tral prob­lem with Anki is that the in­ter­face is re­ally bad. This man­i­fests in var­i­ous ways.

First, it is ugly to look at, par­tic­u­larly the re­view screen. And this di­min­ishes your en­joy­ment of what is al­ready an of­ten bor­ing and frus­trat­ing process.

Second, do­ing sim­ple things is hard. A nice fea­ture of Mochi is that when you start the app you go right into re­view mode. You’re drilling flash­cards be­fore you even re­al­ize it. Anki does­n’t have a study all cards due to­day”, rather, you have to man­u­ally go into a deck and click the Study Now” but­ton. So what I would do is put all my decks un­der a Root” deck, and study that. But this is a hack.

And, third: card in­put uses WYSIWYG edit­ing. So, you’re ei­ther jump­ing from the key­board to the mouse (which in­creases la­tency, and makes flash­card cre­ation more frus­trat­ing) or you have to re­mem­ber all these key­bind­ings to do ba­sic things like make this text a cloze dele­tion” or make this TeX math”.

Finally, plu­g­ins are a dou­ble-edged sword. Because hav­ing the op­tion to use them is nice, but the ex­pe­ri­ence of ac­tu­ally us­ing most plu­g­ins is bad. The whole setup feels janky, like a house of cards. Most of the time, if a fea­ture is not built into the app it­self, I would rather live with­out it than use a plu­gin.

Mochi feels like it was built to ad­dress the main com­plaint about Anki: the in­ter­face. It is in­tu­itive, good look­ing, short­cut-rich. No jank. Instead of WYSIWYG, card text is Markdown: this is de­light­ful.

There’s a few prob­lems. While Markdown is a very low-fric­tion way to write flash­cards, cloze dele­tions in Mochi are very ver­bose. In hash­cards, you can write this:

The equiv­a­lent in Mochi is this:

This is a lot of typ­ing. And you might ob­ject that it’s only a few char­ac­ters longer. But when you’re study­ing from a text­book, or when you’re copy­ing words from a vo­cab­u­lary table, these small fric­tions add up. If writ­ing flash­cards is frus­trat­ing, you’ll write fewer of them: and that means less knowl­edge gained. Dually, a sys­tem that makes flash­card cre­ation as fric­tion­less as pos­si­ble means more flash­cards, and more knowl­edge.

Another prob­lem is that Mochi does­n’t have an equiv­a­lent of Anki’s note

types. For ex­am­ple: you can make a note type for chem­i­cal el­e­ments, with fields like atomic num­ber, sym­bol, name, etc., and write tem­plates to gen­er­ate flash­cards ask­ing ques­tions like:

What is the atomic num­ber of [name]?

What is the sym­bol for [name]?

And so on for other prop­er­ties. This is good. Automation is good. Less work, more flash­cards. Mochi does­n’t have this fea­ture. It has tem­plates, but these are not as pow­er­ful.

But the biggest prob­lem with Mochi, I think, is the al­go­rithm. Until very

re­cently, when they added beta sup­port for FSRS, the al­go­rithm used by Mochi was even sim­pler than SM-2. It was based on mul­ti­pli­ers: re­mem­ber­ing a card mul­ti­plies its in­ter­val by a num­ber >1, for­get­ting a card mul­ti­plies its in­ter­val by a num­ber be­tween 0 and 1.

The sup­posed ra­tio­nale for this is sim­plic­ity: the user can rea­son about the al­go­rithm more eas­ily. But I think this is point­less. The whole point of an SR app is the soft­ware man­ages the sched­ule for you, and the user is com­pletely un­aware of how the sched­uler works. The op­ti­mal­ity is to have the most ad­vanced pos­si­ble sched­ul­ing al­go­rithm (meaning the one that yields the most re­call for the least re­view time) un­der the most in­tu­itive in­ter­face pos­si­ble, and the user just reaps the ben­e­fits.

Obviously with­out an RCT we can’t com­pare Mochi/SM-2/FSRS, but my sub­jec­tive ex­pe­ri­ence of it is that the al­go­rithm works well for the short-term, and fal­ters on the long-term. It’s very bad when you for­get a ma­ture card: if a card has an in­ter­val of sixty days, and you click for­get, you don’t re­set the in­ter­val to one day (which is good, be­cause it helps you re­con­sol­i­date the lost knowl­edge). Rather, the in­ter­val is mul­ti­plied by the for­get mul­ti­plier (by de­fault: 0.5) down to thirty days. What’s the use? If I for­got some­thing af­ter sixty days, I surely won’t have bet­ter re­call in thirty.

You can fix this by set­ting the for­get mul­ti­plier to zero. But you have to know this is how it works, and, cru­cially: I don’t want to con­fig­ure things! I don’t want scheduler pa­ra­me­ter fine­tun­ing” to be yet an­other skill I have to ac­quire: I want the sched­uler to just work.

In gen­eral, I think spaced rep­e­ti­tion al­go­rithms are too op­ti­mistic. I’d rather see cards slightly more of­ten, and spend more time re­view­ing things, than get stuck in forgetting hell”. But de­vel­op­ers have to worry that mak­ing the sys­tem too bur­den­some will hurt re­ten­tion.

In Anki, it’s the in­ter­face that’s frus­trat­ing, but the al­go­rithm works mar­velously. In Mochi, the in­ter­face is de­light­ful, but it’s the al­go­rithm that’s frus­trat­ing. Because you can spend months and months drilling flash­cards, build­ing up your col­lec­tion, but when the cards cross some in­vis­i­ble age thresh­old, you start to for­get them, and the al­go­rithm does not help you re­learn things you have for­got­ten. Eventually I burned out on it and stopped do­ing my re­views, be­cause I ex­pected to for­get every­thing even­tu­ally any­how. And now they added sup­port for FSRS, but by now I have 1700 cards over­due.

Additionally: Mochi has only two but­tons, Forgot” and Remembered”. This is sim­pler for the user, yes, but most SR sched­ul­ing al­go­rithms have more op­tions for a rea­son: dif­fer­ent de­grees of re­call ad­just the card pa­ra­me­ters by dif­fer­ent mag­ni­tudes.

What do I want from a spaced rep­e­ti­tion sys­tem?

The first thing is: card cre­ation must be fric­tion­less. I have learned that the biggest bot­tle­neck in spaced rep­e­ti­tion, for me, is not do­ing the re­views (I am very dis­ci­plined about this and have done SR re­views daily for months on end), it’s not even con­vert­ing con­cep­tual knowl­edge into flash­cards, the biggest bot­tle­neck is just en­ter­ing cards into the sys­tem.

The surest way to shore up your knowl­edge of some con­cept or topic is to write more flash­cards about it: ask­ing the same ques­tion in dif­fer­ent ways, in dif­fer­ent di­rec­tions, from dif­fer­ent an­gles. More vol­ume means you see the same in­for­ma­tion more of­ten, ask­ing in dif­fer­ent ways pre­vents memorizing the shape of the card”, and it acts as a kind of re­dun­dancy: there are mul­ti­ple edges con­nect­ing that bit of knowl­edge to the rest of your mind.

And there have been many times where I have thought: I would make this more solid by writ­ing an­other flash­card. But I opted not to be­cause the mar­ginal flash­card is too ef­fort­ful.

If get­ting cards into the sys­tem in­volves a lot of fric­tion, you write fewer cards. And there’s an op­por­tu­nity cost: the card you don’t write is a con­cept you don’t learn. Integrated across time, it’s en­tire oceans of knowl­edge which are lost.

So: the sys­tem should make card en­try ef­fort­less. This was the guid­ing prin­ci­ple be­hind the de­sign of the hash­cards text for­mat. For ex­am­ple, cloze dele­tions use square brack­ets be­cause in a US key­board, square brack­ets can be typed with­out press­ing shift (compare Mochi’s curly brace). And it’s one bracket, not two. Originally, the for­mat was one line per card, with blank lines sep­a­rat­ing flash­cards, and ques­tion-an­swer cards used slashes to sep­a­rate the sides, like so:

What is the atomic num­ber of car­bon? / 6

The atomic num­ber of [carbon] is [6].

And this is strictly less fric­tion. But it cre­ates a prob­lem for multi-line flash­cards, which are com­mon enough that they should not be a sec­ond-class cit­i­zen. Eventually, I set­tled on the cur­rent for­mat:

Q: What is the atomic num­ber of car­bon?

A: 6

C: The atomic num­ber of [carbon] is [6].

Which is only slightly more typ­ing, and has the ben­e­fit that you can eas­ily vi­su­ally iden­tify where a card be­gins and ends, and what kind of card it is. I spent a lot of time ar­gu­ing back and forth with Claude about what the op­ti­mal for­mat should be.

Another source of fric­tion is not cre­at­ing the cards but edit­ing them. The cen­tral prob­lem is that your knowl­edge changes and im­proves over time. Often text­books take this ap­proach where Chapter 1 in­tro­duces one kind of on­tol­ogy, and by Chapter 3 they tell you, actually that was a lie, here’s the real on­tol­ogy of this sub­ject”, and then you have to go back and edit the old flash­cards to match. Because oth­er­wise you have one card ask­ing, e.g., for the un­der­grad­u­ate de­f­i­n­i­tion of some con­cept, while an­other asks you for the grad­u­ate-level de­f­i­n­i­tion, cre­at­ing am­bi­gu­ity.

For this rea­son, when study­ing from a text­book, I cre­ate a deck for the text­book, with sub-decks for each chap­ter. That makes it easy to match the flash­cards to their source ma­te­r­ial (to en­sure they are aligned) and each chap­ter deck only has a few tens of cards usu­ally, keep­ing them nav­i­ga­ble.

Sometimes you wrote mul­ti­ple cards for the same con­cept, so you have to up­date them all at once. Finding the re­lated ones can be hard if the deck is large. In hash­cards, a deck is just a Markdown file. The cards im­me­di­ately above and be­low a card are usu­ally se­man­ti­cally re­lated. You just scroll up and down and make the ed­its in place.

But why plain-text files in a Git repo? Why not use the above for­mat, but in a normal” app with a data­base?

The vague idea of a spaced rep­e­ti­tion sys­tem where flash­cards are stored as plain-text files in a Git repo had been kick­ing around my cra­nium for a long time. I re­mem­ber ask­ing an Ankihead on IRC circa 2011 if such a thing ex­isted. At some point I read Andy Matuschak’s note on his im­ple­men­ta­tion of an SR sys­tem. In his sys­tem, the flash­cards are colo­cated with prose notes. The no­ta­tion is sim­i­lar to mine: Q and A tags for ques­tion-an­swer cards, and {curly braces} for cloze dele­tions. And the cards are con­tent-ad­dressed: iden­ti­fied by their hash. Which is an ob­vi­ously good idea. But his code is pri­vate and, be­sides, I feel that prose notes and flash­cards are very dif­fer­ent beasts, and I don’t need or want them to mix.

But I think the idea of plain-text spaced rep­e­ti­tion got bumped up the pri­or­ity queue be­cause I spon­ta­neously started us­ing a work­flow that was sim­i­lar to my cur­rent hash­cards work­flow.

When study­ing from a text­book or a web­site, I’d write flash­cards in a Markdown file. Usually, I used a short­hand like [foo] for cloze dele­tions. Then I’d use a Python script to trans­form the short­hand into the {{1::foo}} no­ta­tion used by Mochi. And I’d edit the flash­cards in the file, as my knowl­edge built up and my sense of what was rel­e­vant and im­por­tant to re­mem­ber im­proved. And then, when I was done with the chap­ter or doc­u­ment or what­ever, only then, I would man­u­ally im­port the flash­cards into Mochi.

And it struck me that the last step was kind of un­nec­es­sary. I was al­ready writ­ing my flash­cards as lightly-an­no­tated Markdown in plain-text files. I had

al­ready im­ple­mented FSRS out of cu­rios­ity. I was look­ing for a per­sonal pro­ject to build dur­ing fu­nem­ploy­ment. So hash­cards was by then a very neatly-shaped hole that I just needed to paint in­side.

It turns out that us­ing plain-text stor­age has many syn­er­gies:

You can edit the cards us­ing what­ever ed­i­tor you use, build up a li­brary of

card-cre­at­ing macros, and nav­i­gate the col­lec­tion us­ing the ed­i­tor’s file

browser.

You can query and up­date the col­lec­tion us­ing stan­dard Unix tools, or a

pro­gram­ming lan­guage, e.g. us­ing wc to get the to­tal num­ber of words in the

col­lec­tion, or us­ing awk to make a bulk-up­date to a set of cards.

You can use Git for ver­sion con­trol. Git is in­fi­nitely more fea­ture­ful than

the change-track­ing of any SR app: you can edit mul­ti­ple cards in one com­mit,

branch, merge, use pull re­quests, etc.

You can make your flash­cards pub­lic on GitHub. I of­ten wish peo­ple put more of

them­selves out there: their blog posts, their dot­files, their study notes. And

why not their flash­cards? Even if they are not use­ful to some­one else, there

is some­thing en­joy­able about read­ing what some­one else finds in­ter­est­ing, or

en­joy­able, or worth learn­ing.

You can gen­er­ate flash­cards us­ing scripts (e.g., turn a CSV of for­eign

lan­guage vo­cab­u­lary into a deck of flash­cards), and write a Makefile to tie

the script, data source, and tar­get to­gether. I do this in my

per­sonal deck. Anki’s note types don’t have to be built into hash­cards,

rather, you can DIY it us­ing some Python and make.

The re­sult is a sys­tem where cre­at­ing and edit­ing flash­cards is nearly fric­tion­less, that uses an ad­vanced spaced rep­e­ti­tion sched­uler, and which pro­vides an el­e­gant UI for drilling flash­cards. I hope oth­ers will find it use­ful.

...

Read the original on borretti.me »

3 289 shares, 34 trendiness

Elevated errors across many models

...

Read the original on status.claude.com »

4 226 shares, 13 trendiness

AI and the ironies of automation

AI and the ironies of au­toma­tion - Part 2

AI and the ironies of au­toma­tion - Part 1

It is your fault if your ap­pli­ca­tion is down

View more posts

AI and the ironies of au­toma­tion - Part 2

AI and the ironies of au­toma­tion - Part 2

In the pre­vi­ous post, we dis­cussed sev­eral ob­ser­va­tions, Lisanne Bainbridge made in her much-no­ticed pa­per The ironies of au­toma­tion”, she pub­lished in 1983 and what they mean for the cur­rent white-collar” work au­toma­tion at­tempts lever­ag­ing LLMs and AI agents based on LLMs, still re­quir­ing hu­mans in the loop. We stopped at the end of the first chap­ter, Introduction”, of the pa­per.

In this post, we will con­tinue with the sec­ond chap­ter, Approaches to so­lu­tions”, and see what we can learn there.

However, be­fore we start: Some of the ob­ser­va­tions and rec­om­men­da­tions made in the pa­per must be taken with a grain of salt when ap­ply­ing them to the AI-based au­toma­tion at­tempts of to­day. When mon­i­tor­ing an in­dus­trial pro­duc­tion plant, it is of­ten a mat­ter of sec­onds un­til a hu­man op­er­a­tor must act if some­thing goes wrong to avoid se­vere or even cat­a­strophic ac­ci­dents.

Therefore, it is of the high­est im­por­tance to de­sign in­dus­trial con­trol sta­tions in a way that a hu­man op­er­a­tor can rec­og­nize de­vi­a­tions and mal­func­tions as eas­ily as pos­si­ble and im­me­di­ately trig­ger coun­ter­mea­sures. A lot of work is put into the de­sign of all the dis­plays and con­trols, like, e.g., the well-known emer­gency stop switch in a scream­ing red color that is big enough to be punched with a flat hand, fist or alike within a frac­tion of a sec­ond if needed.

When it comes to AI-based so­lu­tions au­tomat­ing white-col­lar work, we usu­ally do not face such crit­i­cal con­di­tions. However, this is not a rea­son to dis­miss the ob­ser­va­tions and rec­om­men­da­tions in the pa­per eas­ily be­cause, e.g.:

Most com­pa­nies are ef­fi­ciency-ob­sessed. Hence, they also ex­pect AI so­lu­tions to in­crease productivity”, i.e., ef­fi­ciency, to a su­per­hu­man level. If a hu­man is meant to mon­i­tor the out­put of the AI and in­ter­vene if needed, this re­quires that the hu­man needs to com­pre­hend what the AI so­lu­tion pro­duced at su­per­hu­man speed — oth­er­wise we are down to hu­man speed. This pre­sents a quandary that can only be solved if we en­able the hu­man to com­pre­hend the AI out­put at su­per­hu­man speed (compared to pro­duc­ing the same out­put by tra­di­tional means).

Most com­pa­nies have a tra­di­tion of nur­tur­ing a cul­ture of ur­gency and scarcity, re­sult­ing in a lot of pres­sure to­wards and stress for the em­ploy­ees. Stress is known to trig­ger the fight-or-flight mode (an an­cient sur­vival mech­a­nism built into us to cope with dan­ger­ous sit­u­a­tions) which mas­sively re­duces the nor­mal cog­ni­tive ca­pac­ity of a hu­man. While this mech­a­nism sup­ports hu­mans in mak­ing very quick de­ci­sions and tak­ing quick ac­tions (essential in dan­ger­ous sit­u­a­tions), it de­prives them of the abil­ity to con­duct any deeper analy­sis (not be­ing es­sen­tial in dan­ger­ous sit­u­a­tions). If deeper analy­sis is re­quired to make a de­ci­sion, this may take a lot longer than with­out stress — if pos­si­ble at all. This means we need to en­able hu­mans to con­duct deeper analy­sis un­der stress as well or to pro­vide the in­for­ma­tion in a way that elim­i­nates the need for deeper analy­sis (which is not al­ways pos­si­ble).

If we let this sink in (plus a few other as­pects, I did not write down here but you most likely will add in your mind), we quickly come to the con­clu­sion that also in our AI-related au­toma­tion con­text hu­mans are of­ten ex­pected to make quick de­ci­sions and act based on them, of­ten un­der con­di­tions that make it hard (if not im­pos­si­ble) to con­duct any in-depth analy­sis.

If we then also take into ac­count, that de­pend­ing on the sit­u­a­tion a wrong re­sult pro­duced by an AI so­lu­tion which eluded the hu­man op­er­a­tor may have se­vere con­se­quences in the worst case (e.g., as­sume a ma­jor se­cu­rity in­ci­dent due to a missed wrong­do­ing of the AI so­lu­tion), the sit­u­a­tion is not that far away any­more from the sit­u­a­tion in an in­dus­trial plan­t’s con­trol sta­tion.

Summarizing, we surely need to add the nec­es­sary grain of salt, i.e., ask our­selves how strict the tim­ing con­straints in our spe­cific set­ting are to avoid com­par­ing ap­ples and or­anges in the worst case. However, in gen­eral we need to con­sider the whole range of pos­si­ble set­tings which will — prob­a­bly more of­ten than we think — in­clude that hu­mans need to make de­ci­sions in a very short time un­der stress­ful con­di­tions (which makes things more pre­car­i­ous).

This brings us im­me­di­ately to Lisanne Bainbridge’s first rec­om­men­da­tion:

In any sit­u­a­tion where a low prob­a­bil­ity event must be no­ticed quickly then the op­er­a­tor must be given ar­ti­fi­cial as­sis­tance, if nec­es­sary even alarms on alarms.

In other words, the sys­tem must sup­port the hu­man op­er­a­tor as well as pos­si­ble in de­tect­ing a prob­lem, es­pe­cially if it tends to oc­cur rarely. It is a con­se­quence of the monitoring fa­tigue” prob­lem we dis­cussed in the pre­vi­ous post.

Due to the learn­ings peo­ple have made, a lot of ef­fort has been put into the de­sign of the dis­plays, the con­trols and also the alert­ing mech­a­nisms of in­dus­trial pro­duc­tion con­trol sta­tions, mak­ing sure the hu­man op­er­a­tors can make their jobs as good, as stress-free and as re­li­able as pos­si­ble.

The usual idea is that a sin­gle hu­man con­trols a fleet of AI agents that are de­signed to do some kind of job, e.g., writ­ing code. Sometimes, most agents are generic workers”, or­ches­trated by some kind of su­per­vi­sor that del­e­gates parts of the work to the worker agents. Sometimes, the dif­fer­ent agents are specialists”, each for a cer­tain as­pect of the job to be done, that col­lab­o­rate us­ing some kind of chore­og­ra­phy (or are also or­ches­trated by a su­per­vi­sor). While the generic work­ers are eas­ier to set up, the spe­cial­ized work­ers usu­ally pro­duce more ac­cu­rate re­sults.

Because these AI-based agents some­times pro­duce er­rors, a hu­man — in our ex­am­ple a soft­ware de­vel­oper — needs to su­per­vise the AI agent fleet and ide­ally in­ter­venes be­fore the AI agents do some­thing they should not do. Therefore, the AI agents typ­i­cally cre­ate a plan of what they in­tend to do first (which as a side ef­fect also in­creases the like­li­hood that they do not drift off). Then, the hu­man ver­i­fies the plan and ap­proves it if it is cor­rect, and the AI agents ex­e­cute the plan. If the plan is not cor­rect, the hu­man re­jects it and sends the agents back to re­plan­ning, pro­vid­ing in­for­ma­tion about what needs to be al­tered.

Let us take Lisanne Bainbridge’s rec­om­men­da­tion and com­pare it to this ap­proach that is cur­rently best prac­tice” to con­trol an AI agent fleet.

Unless we tell them to act dif­fer­ently, LLMs and also AI agents based on them are quite chatty. Additionally, they tend to com­mu­ni­cate with an air of ut­ter con­vic­tion. Thus, they pre­sent to you this highly de­tailed, multi-step plan of what they in­tend to do, in­clud­ing lots of ex­pla­na­tions, in this per­fectly con­vinced tone. Often, these plans are more than 50 or 100 lines of text, some­times even sev­eral hun­dred lines.

Most of the time, the plans are fine. However, some­times the AI agents mess things up. They make wrong con­clu­sions, or they for­get what they are told to do and drift off — not very of­ten, but it hap­pens. Sometimes the prob­lem is ob­vi­ous at first sight. But more of­ten, it is neatly hid­den some­where be­hind line 123: … and be­cause 2 is big­ger than 3, it is clear, we need to < do some­thing crit­i­cal >”. But be­cause it is so much text the agents flood you with all the time and be­cause the er­ror is hid­den so well be­hind this wall of con­vic­tion, we miss it — and the AI agent does some­thing crit­i­cal wrong.

We can­not blame the per­son for miss­ing the er­ror in the plan. The prob­lem is that this is prob­a­bly the worst UI and UX pos­si­ble for any­one who is re­spon­si­ble for avoid­ing er­rors in a sys­tem that rarely pro­duces er­rors.

But LLM-based agents make er­rors all the time, you may say. Well, not all the time. Sometimes they do. And the bet­ter the in­struc­tions and the setup of the in­ter­act­ing agents, the fewer er­rors they pro­duce. Additionally, we can ex­pect more spe­cial­ized and re­fined agents in the fu­ture that be­come in­creas­ingly bet­ter in their re­spec­tive ar­eas of ex­per­tise. Still, most likely they will never be­come com­pletely er­ror-free be­cause of the un­der­ly­ing tech­nol­ogy that can­not guar­an­tee con­sis­tent cor­rect­ness.

This is the set­ting we need to pon­der if we talk about the user in­ter­face for a hu­man ob­server: a set­ting where the agent fleet only rarely makes er­rors but we still need a hu­man mon­i­tor­ing and in­ter­ven­ing if things should go wrong. It is not yet clear how such an in­ter­face should look like, but most def­i­nitely not as it looks now. Probably we could har­vest some good in­sights from our UX/UI de­sign col­leagues for in­dus­trial pro­duc­tion plant con­trol sta­tions. We would need only to ask them …

Lisanne Bainbridge then makes sev­eral rec­om­men­da­tions re­gard­ing the re­quired train­ing of the hu­man op­er­a­tor. This again is a rich sec­tion, and I can only rec­om­mend read­ing it on your own be­cause it con­tains sev­eral sub­tle yet im­por­tant hints that are hard to bring across with­out cit­ing the whole chap­ter. Here, I will high­light only a few as­pects. She starts with:

[Some points made in the pre­vi­ous sec­tion] make it clear that it can be im­por­tant to main­tain man­ual skills.

Then she talks about let­ting the hu­man op­er­a­tor take over con­trol reg­u­larly, i.e., do the job in­stead of the ma­chine as a very ef­fec­tive train­ing op­tion. Actually, with­out do­ing hands-on work reg­u­larly, the skills of a hu­man ex­pert de­te­ri­o­rate sur­pris­ingly fast.

But if tak­ing over the work reg­u­larly is not an op­tion, e.g., be­cause we want con­tin­u­ous su­per­hu­man pro­duc­tiv­ity lever­ag­ing AI agents (no mat­ter if it makes sense or not), we still need to make sure that the hu­man op­er­a­tor can take over if needed. In such a set­ting, train­ing must take place in some other way, usu­ally us­ing some kind of sim­u­la­tor.

However, there is a prob­lem with sim­u­la­tors, es­pe­cially if hu­man in­ter­ven­tion is only needed (and wanted) if things do not work as ex­pected:

There are prob­lems with the use of any sim­u­la­tor to train for ex­treme sit­u­a­tions. Unknown faults can­not be sim­u­lated, and sys­tem be­hav­iour may not be known for faults which can be pre­dicted but have not been ex­pe­ri­enced.

The con­se­quence of this is­sue is:

This means that train­ing must be con­cerned with gen­eral strate­gies rather than spe­cific re­sponses […]

It is in­ad­e­quate to ex­pect the op­er­a­tor to re­act to un­fa­mil­iar events solely by con­sult­ing op­er­at­ing pro­ce­dures. These can­not cover all the pos­si­bil­i­ties, so the op­er­a­tor is ex­pected to mon­i­tor them and fill in the gaps.

Which leaves us with the irony:

However, it is ironic to train op­er­a­tors in fol­low­ing in­struc­tions and then put them in the sys­tem to pro­vide in­tel­li­gence.

This is a prob­lem we will need to face with AI agents and their su­per­vis­ing hu­mans in the fu­ture, too. The su­per­vis­ing ex­perts are meant to in­ter­vene when­ever things be­come messy, when­ever the AI agents get stuck, of­ten in un­fore­seen ways. These are not reg­u­lar tasks. Often, these are also not the is­sues we ex­pect an AI agent to run into and thus can pro­vide train­ing for. These are ex­tra­or­di­nary sit­u­a­tions, the ones we do not ex­pect — and the more re­fined and spe­cial­ized the AI agents will be­come in the fu­ture, the more of­ten the is­sues that re­quire hu­man in­ter­ven­tion will be of this kind.

How can we train hu­man op­er­a­tors at all to be able to in­ter­vene skill­fully in ex­cep­tional, usu­ally hard to solve sit­u­a­tions?

How can we train a hu­man op­er­a­tor so that their skills re­main sharp over time and they re­main able to ad­dress an ex­cep­tional sit­u­a­tion quickly and re­source­fully?

The ques­tions seem to hint at a sort of para­dox, and an an­swer to both ques­tions is all but ob­vi­ous. At the mo­ment, we still have enough ex­pe­ri­enced sub­ject mat­ter ex­perts that the ques­tions may feel of lower im­por­tance. But if we only start to ad­dress the ques­tions when they be­come press­ing, they will be even harder — if not im­pos­si­ble — to solve.

To end this con­sid­er­a­tion with the words of Lisanne Bainbridge:

Perhaps the fi­nal irony is that it is the most suc­cess­ful au­to­mated sys­tems, with rare need for man­ual in­ter­ven­tion, which may need the great­est in­vest­ment in hu­man op­er­a­tor train­ing.

In other words, we can­not sim­ply take a few avail­able hu­man ex­perts and make them su­per­vise agents that took over their work with­out any fur­ther in­vest­ments in the hu­mans. Instead, we need to train them con­tin­u­ously, and the bet­ter the agents be­come, the more ex­pen­sive the train­ing of the su­per­vi­sors will be­come. I highly doubt that de­ci­sion mak­ers who pri­mar­ily think about sav­ing money when it comes to AI agents are aware of this irony.

As I wrote in the be­gin­ning of first part of this blog se­ries, The ironies of au­toma­tion” is a very rich and dense pa­per. We are still only at the end of the sec­ond chap­ter Approaches to so­lu­tions” which is two and a half pages into the pa­per and there is still a whole third chap­ter called Human-computer col­lab­o­ra­tion” which takes up an­other page un­til we get to the con­clu­sion.

While this third chap­ter also con­tains a lot of valu­able ad­vice that goes well be­yond our fo­cus here, I will leave it to you to read it on your own. As I in­di­cated at the be­gin­ning, this pa­per is more than worth the time spent on it.

However, be­fore fin­ish­ing this lit­tle blog se­ries, I would like to men­tion a new kind of dilemma that Lisanne Bainbridge did not dis­cuss in her pa­per be­cause the sit­u­a­tion was a bit dif­fer­ent with in­dus­trial pro­duc­tion plant au­toma­tion than with AI-agent-based au­toma­tion. But as this topic fits nicely into the just-fin­ished train­ing para­dox sec­tion, I de­cided to add it here.

The is­sue is that just mon­i­tor­ing an AI agent fleet do­ing its work and in­ter­ven­ing if things go wrong usu­ally is not suf­fi­cient, at least not yet. All the things dis­cussed be­fore ap­ply, but there is more to in­ter­act­ing with AI agents be­cause we can­not sim­ply be re­ac­tive with AI agents. We can­not sim­ply watch them do­ing their work and only in­ter­vene if things go wrong. Instead, we ad­di­tion­ally need to be proac­tive with them: We need to di­rect them.

We need to tell the AI agents what to do, what not to do, which chunks to pick and so on. This is ba­si­cally a lead­er­ship role. While you do not lead hu­mans, the kind of work is quite sim­i­lar: You are re­spon­si­ble for the re­sult; you are al­lowed to set di­rec­tions and con­straints, but you do not im­me­di­ately con­trol the work. You only con­trol it through com­mu­ni­cat­ing with the agents and try­ing to di­rect them in the right di­rec­tion with or­ders, with feed­back, with changed or­ders, with set­ting dif­fer­ent con­straints, etcetera.

This is a skill set most peo­ple do not have nat­u­rally. Usually, they need to de­velop it over time. Typically, be­fore peo­ple are put in a lead­er­ship role di­rect­ing hu­mans, they will get a lot of lead­er­ship train­ing teach­ing them the skills and tools needed to lead suc­cess­fully. For most peo­ple, this is es­sen­tial be­cause if they come from the re­ceiv­ing end of or­ders (in the most gen­eral sense of orders”), typ­i­cally they are not used to set­ting di­rec­tion and con­straints. This tends to be a com­pletely new skill they need to learn.

This does not ap­ply only to lead­ing hu­mans but also to lead­ing AI agents. While AI agents are not hu­mans, and thus lead­er­ship will be dif­fer­ent in de­tail, the ba­sic skills and tools needed are the same. This is, BTW, one of the rea­sons why the peo­ple who praise agen­tic AI on LinkedIn and the like are very of­ten man­agers who lead (human) teams. For them, lead­ing an AI agent fleet feels very nat­ural be­cause it is very close to the work they do every day. However, for the peo­ple cur­rently do­ing the work, lead­ing an AI agent fleet usu­ally does not feel nat­ural at all.

However, I have not yet seen any­one re­ceiv­ing any kind of lead­er­ship train­ing be­fore be­ing left alone with a fleet of AI agents, and I still see lit­tle dis­cus­sion about the is­sue. If it does not work prop­erly, you need bet­ter prompts” is the usual re­sponse if some­one strug­gles with di­rect­ing agents suc­cess­fully.

Sorry, but it is not that easy. The is­sue is much big­ger than just op­ti­miz­ing a few prompts. The is­sue is that peo­ple have to change their ap­proach com­pletely to get any piece of work done. Instead of do­ing it di­rectly, they need to learn how to get it done in­di­rectly. They need to learn how to di­rect a group of AI agents ef­fec­tively, how to lead them.

This also adds to the train­ing irony of the pre­vi­ous topic. Maybe the AI agent fleets will be­come good enough in the fu­ture that we can omit the proac­tive part of the work and only need to fo­cus on the re­ac­tive part of the work, the mon­i­tor-and-in­ter­vene part. But un­til then, we need to teach hu­man su­per­vi­sors of AI agent fleets how to lead them ef­fec­tively.

We dis­cussed sev­eral ironies and para­doxes from Lisanne Bainbridge’s The ironies of au­toma­tion” and how they also ap­ply to agen­tic AI. We looked at the un­learn­ing and re­call dilemma and what it means for the next gen­er­a­tion of hu­man su­per­vi­sors. We dis­cussed mon­i­tor­ing fa­tigue and the sta­tus is­sue. We looked at the UX and UI de­fi­cien­cies of cur­rent AI agents and the train­ing para­dox. And we fi­nally looked at the lead­er­ship dilemma, which Lisanne Bainbridge did not dis­cuss in her pa­per but which com­ple­ments the train­ing para­dox.

I would like to con­clude with the con­clu­sion of Lisanne Bainbridge:

[…] hu­mans work­ing with­out time-pres­sure can be im­pres­sive prob­lem solvers. The dif­fi­culty re­mains that they are less ef­fec­tive when un­der time pres­sure. I hope this pa­per has made clear both the irony that one is not by au­tomat­ing nec­es­sar­ily re­mov­ing the dif­fi­cul­ties, and also the pos­si­bil­ity that re­solv­ing them will re­quire even greater tech­no­log­i­cal in­ge­nu­ity than does clas­sic au­toma­tion.

I could not agree more.

I think over time we will be­come clear on how much The ironies of au­toma­tion” also ap­plies to au­toma­tion done with AI agents and that we can­not ig­nore the in­sights known for more than 40 years mean­while. I am also re­ally cu­ri­ous how the so­lu­tions to the ironies and para­doxes will look like.

Until then, I hope I gave you a bit of food for thought to pon­der. If you should have some good ideas re­gard­ing the ironies and how to ad­dress them, please do not hes­i­tate to share them with the com­mu­nity. We learn best by shar­ing and dis­cussing, and maybe your con­tri­bu­tion will be a step to­wards solv­ing the is­sues dis­cussed …

AI and the ironies of au­toma­tion - Part 1

Web site and blog. Writing about IT most of the time.

AI and the ironies of au­toma­tion - Part 2

AI and the ironies of au­toma­tion - Part 1

It is your fault if your ap­pli­ca­tion is down

View more posts

I’m Uwe, trav­el­ling the world of IT for many years. Worked in many roles in and around IT. Sharing my thought, ideas and in­sights here. Explorer. Connector. Sharer. Coder. Writer. Human. More. Order may vary.

Learn More

...

Read the original on www.ufried.com »

5 212 shares, 16 trendiness

the enterprise honeymoon is over

I’ve used GraphQL, specif­i­cally Apollo Client and Server, for a cou­ple of years in a real en­ter­prise-grade ap­pli­ca­tion.

Not a toy app. Not a green­field startup. A proper pro­duc­tion setup with mul­ti­ple teams, BFFs, down­stream ser­vices, ob­serv­abil­ity re­quire­ments, and real users.

And af­ter all that time, I’ve come to a pretty bor­ing con­clu­sion:

GraphQL solves a real prob­lem, but that prob­lem is far more niche than peo­ple ad­mit. In most en­ter­prise se­tups, it’s al­ready solved else­where, and when you add up the trade­offs, GraphQL of­ten ends up be­ing a net neg­a­tive.

This is­n’t a GraphQL bad” post. It’s a GraphQL af­ter the hon­ey­moon” post.

The main prob­lem GraphQL tries to solve is over­fetch­ing.

The idea is sim­ple and ap­peal­ing:

* the client asks for ex­actly the fields it needs

* no more, no less

* no back­end changes for every new UI re­quire­ment

On pa­per, that’s great. In prac­tice, things are messier.

Most en­ter­prise fron­tend ar­chi­tec­tures al­ready have a BFF (Backend for Frontend).

* re­turn ex­actly what the UI needs

If you’re us­ing REST be­hind a BFF, over­fetch­ing is al­ready solv­able. The BFF can scope down re­sponses and re­turn only what the UI cares about.

Yes, GraphQL can also do this. But here’s the part peo­ple gloss over.

Most down­stream ser­vices are still REST.

So now your GraphQL layer still has to over­fetch from down­stream REST APIs, then re­shape the re­sponse. You did­n’t elim­i­nate over­fetch­ing. You just moved it down a layer.

That alone sig­nif­i­cantly di­min­ishes GraphQL’s main sell­ing point.

There is a case where GraphQL wins here. If mul­ti­ple pages hit the same end­point but need slightly dif­fer­ent fields, GraphQL lets you scope those dif­fer­ences per query.

But let’s be hon­est about the trade.

You’re usu­ally talk­ing about sav­ing a hand­ful of fields per re­quest, in ex­change for:

That’s a very ex­pen­sive trade for a few ex­tra kilo­bytes.

* re­turn what the UI needs

With GraphQL, you now have to:

GraphQL op­ti­mizes con­sump­tion at the cost of pro­duc­tion speed.

In an en­ter­prise en­vi­ron­ment, pro­duc­tion speed mat­ters more than the­o­ret­i­cal el­e­gance.

This one does­n’t get talked about enough.

GraphQL has this weird sta­tus code con­ven­tion:

* 400 if the query can’t be parsed

* 200 with an er­rors ar­ray if some­thing failed dur­ing ex­e­cu­tion

* 200 if it suc­ceeded or par­tially suc­ceeded

* 500 if the server is un­reach­able

From an ob­serv­abil­ity stand­point, this is painful.

If you fil­ter dash­boards by 2XX, you know those re­quests suc­ceeded.

With GraphQL, a 200 can still mean par­tial or full fail­ure.

Yes, Apollo lets you cus­tomize this be­hav­ior. But that’s kind of the point. You’re con­stantly pay­ing a tax in ex­tra con­fig­u­ra­tion, ex­tra con­ven­tions, and ex­tra men­tal over­head just to get back to some­thing REST gives you out of the box.

This mat­ters when you’re on call, not when you’re read­ing blog posts.

If you have two queries where only one field dif­fers, Apollo treats them as sep­a­rate queries. You then have to man­u­ally wire things so:

* only the dif­fer­ing field is fetched

* you still have a roundtrip

* de­bug­ging cache is­sues be­comes its own prob­lem

Meanwhile, REST hap­pily over­fetches a few ex­tra fields, caches the whole re­sponse, and moves on. Extra kilo­bytes are cheap. Complexity is­n’t.

Apollo ex­pects every ob­ject to have an id or _id field by de­fault, or you need to con­fig­ure a cus­tom iden­ti­fier.

That as­sump­tion does not hold in many en­ter­prise APIs.

So now the BFF has to gen­er­ate IDs lo­cally just to sat­isfy the GraphQL client.

* you’re al­ways fetch­ing one ex­tra field any­way

Which is ironic, con­sid­er­ing the orig­i­nal goal was to re­duce over­fetch­ing.

GraphQL is sim­ply not a good fit for bi­nary data.

In prac­tice, you end up:

* then us­ing REST to fetch the file any­way

Embedding large pay­loads like PDFs di­rectly in GraphQL re­sponses leads to bloated re­sponses and worse per­for­mance.

This alone breaks the single API story.

Most fron­tend and full-stack de­vel­op­ers are far more ex­pe­ri­enced with REST than GraphQL.

That learn­ing curve cre­ates fric­tion, es­pe­cially when teams need to move fast.

REST is bor­ing, but bor­ing scales ex­tremely well.

* the need to trace which re­solver failed and why

All of this adds in­di­rec­tion.

Compare that to a sim­ple REST setup where:

Simple er­rors are eas­ier to rea­son about than el­e­gant ones.

But in most en­ter­prise en­vi­ron­ments:

* you al­ready have BFFs

* over­fetch­ing is not your biggest prob­lem

When you add every­thing up, GraphQL of­ten ends up solv­ing a nar­row prob­lem while in­tro­duc­ing a broader set of new ones.

That’s why, af­ter us­ing it in pro­duc­tion for years, I’d say this:

GraphQL is­n’t bad. It’s just niche. And you prob­a­bly don’t need it.

Especially if your ar­chi­tec­ture al­ready solved the prob­lem it was de­signed for.

...

Read the original on johnjames.blog »

6 206 shares, 12 trendiness

How we got hit by Shai-Hulud: A complete post-mortem

On November 25th, 2025, we were on a rou­tine Slack hud­dle de­bug­ging a pro­duc­tion is­sue when we no­ticed some­thing strange: a PR in one of our in­ter­nal re­pos was sud­denly closed, showed zero changes, and had a sin­gle com­mit from… Linus Torvalds?

The com­mit mes­sage was just init.”

Within sec­onds, our #git Slack chan­nel ex­ploded with no­ti­fi­ca­tions. Dozens of force-pushes. PRs clos­ing across mul­ti­ple repos­i­to­ries. All at­trib­uted to one of our en­gi­neers.

We had been com­pro­mised by Shai-Hulud 2.0, a so­phis­ti­cated npm sup­ply chain worm that com­pro­mised over 500 pack­ages, af­fected 25,000+ repos­i­to­ries, and spread across the JavaScript ecosys­tem. We weren’t alone: PostHog, Zapier, AsyncAPI, Postman, and ENS were among those hit.

This is the com­plete story of what hap­pened, how we re­sponded, and what we’ve changed to pre­vent this from hap­pen­ing again.

No Trigger.dev pack­ages were ever com­pro­mised. The @trigger.dev/* pack­ages and trig­ger.dev CLI were never in­fected with Shai-Hulud mal­ware. This in­ci­dent in­volved one of our en­gi­neers in­stalling a com­pro­mised pack­age on their de­vel­op­ment ma­chine, which led to cre­den­tial theft and unau­tho­rized ac­cess to our GitHub or­ga­ni­za­tion. Our pub­lished pack­ages re­mained safe through­out.

On the evening of November 24th, around 20:27 UTC (9:27 PM lo­cal time in Germany), one of our en­gi­neers was ex­per­i­ment­ing with a new pro­ject. They ran a com­mand that trig­gered pnpm in­stall. At that mo­ment, some­where in the de­pen­dency tree, a ma­li­cious pack­age ex­e­cuted.

We don’t know ex­actly which pack­age de­liv­ered the pay­load. The en­gi­neer was ex­per­i­ment­ing at the time and may have deleted the pro­ject di­rec­tory as part of cleanup. By the time we in­ves­ti­gated, we could­n’t trace back to the spe­cific pack­age. The en­gi­neer checked their shell his­tory and they’d only run in­stall com­mands in our main trig­ger repo, cloud repo, and one ex­per­i­men­tal pro­ject.

This is one of the frus­trat­ing re­al­i­ties of these at­tacks: once the mal­ware runs, iden­ti­fy­ing the source be­comes ex­tremely dif­fi­cult. The pack­age does­n’t an­nounce it­self. The pnpm in­stall com­pletes suc­cess­fully. Everything looks nor­mal.

What we do know is that the Shai-Hulud mal­ware ran a pre­in­stall script that:

When the en­gi­neer later re­cov­ered files from their com­pro­mised lap­top (booted in re­cov­ery mode), they found the tell­tale signs:

The .trufflehog-cache di­rec­tory and truf­fle­hog_3.91.1_­dar­win_amd64.tar.gz file found on the com­pro­mised ma­chine. The ex­tract di­rec­tory was empty, likely cleaned up by the mal­ware to cover its tracks.

The at­tacker had ac­cess to our en­gi­neer’s GitHub ac­count for 17 hours be­fore do­ing any­thing vis­i­ble. According to our GitHub au­dit logs, they op­er­ated me­thod­i­cally.

Just over two hours af­ter the ini­tial com­pro­mise, the at­tacker val­i­dated their stolen cre­den­tials and be­gan mass cloning:

The si­mul­ta­ne­ous ac­tiv­ity from US and India con­firmed we were deal­ing with a sin­gle at­tacker us­ing mul­ti­ple VPNs or servers, not sep­a­rate ac­tors.

While our en­gi­neer slept in Germany, the at­tacker con­tin­ued their re­con­nais­sance. More cloning at 02:56-02:59 UTC (middle of the night in Germany), spo­radic ac­tiv­ity un­til 05:32 UTC. Total re­pos cloned: 669 (527 from US in­fra­struc­ture, 142 from India).

Here’s where it gets un­set­tling. Our en­gi­neer woke up and started their nor­mal work­day:

The at­tacker was mon­i­tor­ing our en­gi­neer’s ac­tiv­ity while they worked, un­aware they were com­pro­mised.

During this pe­riod, the at­tacker cre­ated repos­i­to­ries with ran­dom string names to store stolen cre­den­tials, a known Shai-Hulud pat­tern:

They also cre­ated three re­pos marked with Sha1-Hulud: The Second Coming” as a call­ing card. These repos­i­to­ries were empty by the time we ex­am­ined them, but based on the doc­u­mented Shai-Hulud be­hav­ior, they likely con­tained triple base64-en­coded cre­den­tials.

At 15:27 UTC on November 25th, the at­tacker switched from re­con­nais­sance to de­struc­tion.

The at­tack be­gan on our cloud repo from India-based in­fra­struc­ture:

The at­tack con­tin­ued on our main repos­i­tory:

At 15:32:43-46 UTC, 12 PRs on json­hero-web were closed in 3 sec­onds. Clearly au­to­mated. PRs #47, #169, #176, #181, #189, #190, #194, #197, #204, #206, #208 all closed within a 3-second win­dow.

Our crit­i­cal in­fra­struc­ture repos­i­tory was tar­geted next:

The fi­nal PR was closed on json-in­fer-types at 15:37:13 UTC.

We got a lucky break. One of our team mem­bers was mon­i­tor­ing Slack when the flood of no­ti­fi­ca­tions started:

Our #git Slack chan­nel dur­ing the at­tack. A wall of force-pushes, all with com­mit mes­sage init.”

Every ma­li­cious com­mit was au­thored as:

An at­tacked branch: a sin­gle init” com­mit at­trib­uted to Linus Torvalds, thou­sands of com­mits be­hind main.

We haven’t found re­ports of other Shai-Hulud vic­tims see­ing this same Linus Torvalds” van­dal­ism pat­tern. The wor­m’s doc­u­mented be­hav­ior fo­cuses on cre­den­tial ex­fil­tra­tion and npm pack­age prop­a­ga­tion, not repos­i­tory de­struc­tion. This de­struc­tive phase may have been unique to our at­tacker, or per­haps a man­ual fol­low-up ac­tion af­ter the au­to­mated worm had done its cre­den­tial har­vest­ing.

Within 4 min­utes of de­tec­tion we iden­ti­fied the com­pro­mised ac­count, re­moved them from the GitHub or­ga­ni­za­tion, and the at­tack stopped im­me­di­ately.

Our in­ter­nal Slack dur­ing those first min­utes:

add me to the call @here”

Nick could you dou­ble check Infisical for any ma­chine iden­ti­ties”

can some­one also check whether there are any re­ports of com­pro­mised pack­ages in our CLI deps?”

Protected branch re­jec­tions: 4. Some of our repos­i­to­ries have main branch pro­tec­tion en­abled, but we had not en­abled it for all repos­i­to­ries at the time of the in­ci­dent.

npm pack­ages were not com­pro­mised. This is the dif­fer­ence be­tween our re­pos got van­dal­ized” and our pack­ages got com­pro­mised.”

Our en­gi­neer did­n’t have an npm pub­lish­ing to­ken on their ma­chine, and even if they did we had al­ready re­quired 2FA for pub­lish­ing to npm. Without that, Shai-Hulud would have pub­lished ma­li­cious ver­sions of @trig­ger.dev/​sdk, @trig­ger.dev/​core, and oth­ers, po­ten­tially af­fect­ing thou­sands of down­stream users.

Production data­bases or any AWS re­sources were not ac­cessed. Our AWS CloudTrail au­dit showed only read op­er­a­tions from the com­pro­mised ac­count:

These were con­firmed to be le­git­i­mate op­er­a­tions by our en­gi­neer.

One nice sur­prise: AWS ac­tu­ally sent us a proac­tive alert about Shai-Hulud. They de­tected the mal­ware’s char­ac­ter­is­tic be­hav­ior (ListSecrets, GetSecretValue, BatchGetSecretValue API calls) on an old test ac­count that had­n’t been used in months, so we just deleted it. But ku­dos to AWS for the proac­tive de­tec­tion and no­ti­fi­ca­tion.

GitHub does­n’t have server-side re­flog. When some­one force-pushes, that his­tory is gone from GitHub’s servers.

But we found ways to re­cover.

Push events are re­tained for 90 days via the GitHub Events API. We wrote a script that fetched pre-at­tack com­mit SHAs:

Public repos­i­tory forks still con­tained orig­i­nal com­mits. We used these to ver­ify and re­store branches.

Developers who had­n’t run git fetch –prune (all of us?) still had old SHAs in their lo­cal re­flog.

Within 7 hours, all 199 branches were re­stored.

During the in­ves­ti­ga­tion, our en­gi­neer was go­ing through files re­cov­ered from the com­pro­mised lap­top and dis­cov­ered some­thing con­cern­ing: the pri­vate key for our GitHub App was in the trash folder.

When you cre­ate a pri­vate key in the GitHub App set­tings, GitHub au­to­mat­i­cally down­loads it. The en­gi­neer had cre­ated a key at some point, and while the ac­tive file had been deleted, it was still in the trash, po­ten­tially ac­ces­si­ble to TruffleHog.

Our GitHub App has the fol­low­ing per­mis­sions on cus­tomer repos­i­to­ries:

To gen­er­ate valid ac­cess to­kens, an at­tacker would need both the pri­vate key (potentially com­pro­mised) and the in­stal­la­tion ID for a spe­cific cus­tomer (stored in our data­base which was not com­pro­mised, not on the com­pro­mised ma­chine).

We found no ev­i­dence of unau­tho­rized ac­cess to any cus­tomer repos­i­to­ries. The at­tacker would have needed in­stal­la­tion IDs from our data­base to gen­er­ate to­kens, and our data­base was not com­pro­mised as pre­vi­ously men­tioned.

However, we can­not com­pletely rule out the pos­si­bil­ity. An at­tacker with the pri­vate key could the­o­ret­i­cally have called the GitHub API to enu­mer­ate all in­stal­la­tions. We’ve con­tacted GitHub Support to re­quest ad­di­tional ac­cess logs. We’ve also an­a­lyzed the web­hook pay­loads to our GitHub app, look­ing for sus­pi­cious push or PR ac­tiv­ity from con­nected in­stal­la­tions & repos­i­to­ries. We haven’t found any ev­i­dence of unau­tho­rized ac­tiv­ity in these web­hook pay­loads.

We’ve sent out an email to po­ten­tially ef­fected cus­tomers to no­tify them of the in­ci­dent with de­tailed in­struc­tions on how to check if they were af­fected. Please check your email for more de­tails if you’ve used our GitHub app.

For those in­ter­ested in the tech­ni­cal de­tails, here’s what we learned about the mal­ware from Socket’s analy­sis and our own in­ves­ti­ga­tion.

When npm runs the pre­in­stall script, it ex­e­cutes set­up_bun.js:

Returns im­me­di­ately so npm in­stall com­pletes suc­cess­fully with no warn­ings

The mal­ware runs in the back­ground while you think every­thing is fine.

The pay­load uses TruffleHog to scan $HOME for GitHub to­kens (from env vars, gh CLI con­fig, git cre­den­tial helpers), AWS/GCP/Azure cre­den­tials, npm to­kens from .npmrc, en­vi­ron­ment vari­ables con­tain­ing any­thing that looks like a se­cret, and GitHub Actions se­crets (if run­ning in CI).

Stolen cre­den­tials are up­loaded to a newly-cre­ated GitHub repo with a ran­dom name. The data is triple base64-en­coded to evade GitHub’s se­cret scan­ning.

If an npm pub­lish­ing to­ken is found, the mal­ware val­i­dates the to­ken against the npm reg­istry, fetches pack­ages main­tained by that ac­count, down­loads each pack­age, patches it with the mal­ware, bumps the ver­sion, and re-pub­lishes, in­fect­ing more pack­ages.

This is how the worm spread through the npm ecosys­tem, start­ing from PostHog’s com­pro­mised CI on November 24th at 4:11 AM UTC. Our en­gi­neer was in­fected roughly 16 hours af­ter the ma­li­cious pack­ages went live.

If no cre­den­tials are found to ex­fil­trate or prop­a­gate, the mal­ware at­tempts to delete the vic­tim’s en­tire home di­rec­tory. Scorched earth.

File ar­ti­facts to look for: set­up_bun.js, bun_en­vi­ron­ment.js, cloud.json, con­tents.json, en­vi­ron­ment.json, truf­fleS­e­crets.json, ac­tion­sSe­crets.json, .trufflehog-cache/ di­rec­tory.

This pre­vents pre­in­stall, postin­stall, and other life­cy­cle scripts from run­ning. It’s ag­gres­sive and some pack­ages will break, but it’s the only re­li­able pro­tec­tion against this class of at­tack.

We up­graded to pnpm 10. This was sig­nif­i­cant ef­fort (had to mi­grate through pnpm 9 first), but pnpm 10 brings crit­i­cal se­cu­rity im­prove­ments. Scripts are ig­nored by de­fault. You can ex­plic­itly whitelist pack­ages that need to run scripts via pnpm.only­Built­De­pen­den­cies. And the min­i­mum­Re­leaseAge set­ting pre­vents in­stalling pack­ages pub­lished re­cently.

To whitelist pack­ages that le­git­i­mately need build scripts:

This prompts you to se­lect which pack­ages to al­low (like es­build, prisma, sharp).

We switched npm pub­lish­ing to OIDC. No more long-lived npm to­kens any­where. Publishing now uses npm’s trusted pub­lish­ers with GitHub Actions OIDC. Even if an at­tacker com­pro­mises a de­vel­oper ma­chine, they can’t pub­lish pack­ages be­cause there are no cre­den­tials to steal. Publishing only hap­pens through CI with short-lived, scoped to­kens.

We en­abled branch pro­tec­tion on all repos­i­to­ries. Not just crit­i­cal re­pos or just OSS re­pos. Every repos­i­tory with mean­ing­ful code now has branch pro­tec­tion en­abled.

We’ve adopted Granted for AWS SSO. Granted en­crypts SSO ses­sion to­kens on the client side, un­like the AWS CLI which stores them in plain­text.

Based on PostHog’s analy­sis of how they were ini­tially com­pro­mised (via pul­l_re­quest_­tar­get), we’ve re­viewed our GitHub Actions work­flows. We now re­quire ap­proval for ex­ter­nal con­trib­u­tor work­flow runs on all our repos­i­to­ries (previous pol­icy was only for pub­lic repos­i­to­ries).

The abil­ity for pack­ages to run ar­bi­trary code dur­ing in­stal­la­tion is the at­tack sur­face. Until npm fun­da­men­tally changes, add this to your ~/.npmrc:

Yes, some things will break. Whitelist them ex­plic­itly. The in­con­ve­nience is worth it.

pnpm 10 ig­nores scripts by de­fault and lets you set a min­i­mum age for pack­ages:

Newly pub­lished pack­ages can’t be in­stalled for 3 days, giv­ing time for ma­li­cious pack­ages to be de­tected.

Branch pro­tec­tion takes 30 sec­onds to en­able. It pre­vents at­tack­ers from push­ing to a main branch, po­ten­tially ex­e­cut­ing ma­li­cious GitHub ac­tion work­flows.

Long-lived npm to­kens on de­vel­oper ma­chines are a li­a­bil­ity. Use trusted pub­lish­ers with OIDC in­stead.

If you don’t need a cre­den­tial on your lo­cal ma­chine, don’t have it there. Publishing should hap­pen through CI only.

Our #git Slack chan­nel is noisy. That noise saved us.

One of the hard­est parts of this in­ci­dent was that it hap­pened to a per­son.

Sorry for all the trou­ble guys, ter­ri­ble ex­pe­ri­ence”

Our com­pro­mised en­gi­neer felt ter­ri­ble, even though they did ab­solutely noth­ing wrong. It could have hap­pened to any team mem­ber.

Running npm in­stall is not neg­li­gence. Installing de­pen­den­cies is not a se­cu­rity fail­ure. The se­cu­rity fail­ure is in an ecosys­tem that al­lows pack­ages to run ar­bi­trary code silently.

They also dis­cov­ered that the at­tacker had made their GitHub ac­count star hun­dreds of ran­dom repos­i­to­ries dur­ing the com­pro­mise. Someone even emailed us: hey you starred my repo but I think it was be­cause you were hacked, maybe re­move the star?”

Have ques­tions about this in­ci­dent? Reach out on Twitter/X or Discord.

...

Read the original on trigger.dev »

7 180 shares, 14 trendiness

Developing a food-safe finish for my wooden spoons and cups

You know what they say in the world of prod­ucts: fast, cheap, good; pick two

Which is very sim­i­lar to my ex­pe­ri­ence when try­ing to find the most suit­able wood fin­ish for my hand carved wooden spoons and cof­fee cups.

* cures fast (in less than 2 days)

* is food safe (can be used on things you eat or drink from, like spoons and cups)

* is free of sol­vents (doesn’t smell of nasty chem­i­cals that make you dizzy every time you ap­ply it)

* and with the hard re­quire­ment of mak­ing wood hy­dropho­bic and leav­ing a vi­su­ally pleas­ant sheen with­out cre­at­ing a pla­s­ticky layer

Sure, we have pure tung oil which does­n’t need any sol­vent, has a pleas­ant nutty smell, and cures into a food-safe hy­dropho­bic poly­mer in­side the wood fibers. But it takes 2 to 4 weeks for the cur­ing to hap­pen de­pend­ing on oxy­gen in­take, and the fin­ish is quite matte and bor­ing.

While tung oil is nat­ural, that does­n’t mean you can in­gest it. It is a pow­er­ful ir­ri­tant in its liq­uid form, it is only food-safe af­ter cur­ing into its in­ert poly­mer state.

There’s also the more rare poly­mer­ized (or heat-bod­ied) tung oil, which is a honey-like vis­cous oil that cures in a few days be­cause it was heated to very high tem­per­a­tures in the ab­sence of oxy­gen. That would be ideal ex­cept I can’t find it any­where around me to buy, and it would most likely need thin­ning with cit­rus oil sol­vent (or D-limonene).

Citrus oil has a nice but way too po­tent smell of or­ange peel. It might seem pleas­ant at first com­pared to the chem­i­cal smell of naph­tha and white spir­its, but it can be too much if you fin­ish small wooden ob­jects of­ten like I do.

ash cup, in the process of be­ing oiled with tung oil

And there are plenty other dry­ing oils, the most well-known be­ing lin­seed oil, which is in­deed ed­i­ble but has the un­for­tu­nate dis­ad­van­tages of yel­low­ing over time, tak­ing ages to cure and hav­ing a per­sis­tent oily-grassy fla­vor. Polymerized lin­seed oil (aka stand oil) cures faster but still re­tains the nasty fla­vor.

Careful not to con­fuse it with boiled lin­seed oil or BLO, which uses metal­lic dry­ing agents like cobalt or man­ganese salts.

The boiled name comes from the old prac­tice of heat­ing the lin­seed oil with lead ox­ide in­side, ef­fec­tively short­en­ing the ox­i­da­tion process. But nowa­days there’s no heat in­volved in BLO.

More de­tails in The low­down on BLO

The oil paint­ing world has ex­pe­ri­ence with many dry­ing oils like saf­flower oil, wal­nut oil, poppy seed oil, hemp seed oil. Unfortunately they cure slower and into a less durable film while also be­ing rare and ex­pen­sive so they aren’t good al­ter­na­tives for wooden uten­sils.

For a good few months I used Osmo Polyx Oil which is a sol­vent-based hard­wax oil. Its safety datasheet and full de­c­la­ra­tion of in­gre­di­ents men­tion about 50% of it be­ing white spirit sol­vent, and the rest is com­posed of nat­ural oils processed to be­come dry­ing oils, and a small amount of hard car­nauba wax.

It is fast cur­ing in less than a day, leaves a beau­ti­ful shim­mer on the wood sur­face, it is food safe af­ter cur­ing, but smells aw­ful be­cause of the sol­vents.

In the win­ter months I carve in­doors and have to fin­ish the pieces in­doors as well, and the hor­ri­ble sol­vent smell fills my house for a whole day. I seem to have be­come sen­si­tized to the smell and now I have al­most a full can of Osmo that I can’t use with­out a mask, even out­doors.

There’s also Rubio Monocoat and other two-com­po­nent hard­wax oils where the base com­po­nent is usu­ally a sol­vent-free blend of dry­ing oils and waxes, and the ac­cel­er­a­tor com­po­nent is Hexamethylene di­iso­cyanate or HDI. The base com­po­nent can cure on its own in about 3 weeks and the ac­cel­er­a­tor short­ens the cur­ing time to less than a day.

This al­ter­na­tive cures fast into an in­ert and food safe poly­mer, smells like ap­ple pie, and the fin­ish has a slight satin ef­fect. But it’s re­ally hard to mix prop­erly and ap­ply on small wooden ob­jects like spoons and cups. I al­most al­ways use too much ac­cel­er­a­tor, the mix­ture ends up too vis­cous and hard to spread on the wood and the con­stant open­ing of the bot­tles and cans makes the com­po­nents dry pre­ma­turely in their con­tain­ers.

However, this idea of blend­ing dry­ing oils with hard wax seems to be promis­ing and it’s the path I con­tin­ued on de­vel­op­ing.

Food-safe epoxy is an­other al­ter­na­tive, but I hate both the idea of us­ing syn­thetic plas­tics and their pla­s­ticky look takes away from the ex­pe­ri­ence of us­ing wooden uten­sils.

Why even use wood if you’re go­ing to cover it in a layer of clear plas­tic?

Many peo­ple also rec­om­mend other ed­i­ble oils like co­conut oil, olive oil etc. But these don’t cure and don’t pro­vide any pro­tec­tion for hot liq­uids. They ei­ther go ran­cid in­side the wood fiber or get washed out af­ter us­ing the wooden ob­ject.

Some rec­om­mend non-ed­i­ble petrol-based min­eral oil (aka liq­uid par­rafin) be­cause it does­n’t go ran­cid, but has the same ef­fect of not ac­tu­ally do­ing much for pro­tec­tion and will leak into hot liq­uids.

Beeswax is of­ten used by kuksa mak­ers (traditional Scandinavian wooden cups) but wax mol­e­cules are too large to pen­e­trate wood fibers well, and it has a low melt­ing point of 60℃ (140°F) so hot­ter liq­uids are out of the ques­tion.

Carnauba wax has a higher melt­ing point at 80℃ (176°F) and is harder than beeswax, but it has a glossy fin­ish, hav­ing a sim­i­lar look to epoxy resin af­ter buff­ing.

The ideal fin­ish should com­bine the durable hy­dropho­bic prop­er­ties of fiber-pen­e­trat­ing tung oil with the fast dry­ing prop­er­ties of a top wax layer, in an easy to ap­ply but sol­vent-free blend.

Some carvers use urushi lac­quer which is the sap from a tree com­mon to Japan. The re­sult is a hard and glossy fin­ish that can re­sist tem­per­a­tures of over 300℃ (572°F), but the look and process of ap­pli­ca­tion is far from what I’m look­ing for.

To en­sure cur­ing is com­plete, it needs 10 to 20 very thin coats over many months in a warm and hu­mid en­vi­ron­ment. The wood then takes this dark brown color, re­gard­less of what wood you started with, which is the op­po­site of what I want.

I work with fruit and flower woods that are less com­mon in wood­work­ing (apple, fig, jas­mine etc.) and I want peo­ple to know that and ex­pe­ri­ence what that spe­cific wood looks and feels like. I want to keep their orig­i­nal hues and tints and ac­cen­tu­ate the wood grain of each piece.

Someone from Israel bought a spoon I made from fig tree wood, but still asked about it a bit in­cred­u­lously. It had green­ish light wood grain, with a bit of un­touched bark kept on the han­dle and a wonky curve that fol­lowed the shape of the tree branch it was made from.

They have many fig trees there but had never seen such a thing made from their wood, so they felt a con­nec­tion to their moth­er­land in that usual ob­ject.

My mother-in-law cut a large lilac tree and gave me some thick branches. It’s a wood that cracks very eas­ily while dry­ing, and I could­n’t use most of it. But the few things I made from it, I gifted back to my wife’s mother and sis­ters in the form of cook­ing spoons and are still cher­ished by them to­day.

Its pas­tel pur­ple grain ac­cents re­mind them clearly of the tree that used to flower every spring in their yard.

A brown lac­quer would never be able to cre­ate this ef­fect, and that is why I’m still try­ing to find the per­fect nat­ural oil based fin­ish.

This is ba­si­cally poly­silox­ane dis­solved in al­co­hol and isoparaf­fin sol­vent. After 3 weeks it cures into a food-safe, hy­dropho­bic layer which is durable, but not very good look­ing in my eyes.

It leaves the wood look­ing bare, with­out the color en­hanc­ing and rip­pling ef­fect of oil. Some might pre­fer that, es­pe­cially peo­ple that worked hard on get­ting a very shiny knife fin­ish on their carv­ing.

In my case, this is not the fin­ish I’m look­ing for be­cause of the 3-week cur­ing time, the sol­vent-based so­lu­tion, the col­or­less look and the fact that this fin­ish is very ex­pen­sive and hard to find out­side Japan.

Here’s some more in­for­ma­tion from a wood­turn­er’s ex­pe­ri­ence with the fin­ish: Liquid Glass Wood Finish — Update

For the im­pa­tient, here’s a com­par­i­son video on how the hard­wax oil blends look and per­form in a wa­ter test on some plum wood blanks.

My ex­per­i­ments started sim­ple, with melt­ing about 10g of car­nauba wax flakes into 40g of pure tung oil.

Most peo­ple rec­om­mend a dou­ble-boiler or bain-marie ap­proach to melt­ing the wax. That’s be­cause the heat source would be a con­tainer of boil­ing wa­ter which can never get above 100℃ (212°F), a safe tem­per­a­ture to avoid reach­ing the flash point of these oils.

I just drop a spoon­ful of car­nauba flakes into a glass jar of tung oil and place it in the mi­crowave for a minute un­til every­thing be­comes liq­uid.

For small quan­ti­ties, the mi­crowave works won­ders, and there’s no dan­ger of over­heat­ing the oil or geli­fy­ing it be­cause it cools off rapidly.

* pour the tung oil into a glass jar or ce­ramic con­tainer

* drop the car­nauba wax flakes into the oil and stir to dis­perse the flakes

* place in the mi­crowave for 30 sec­onds then stir again for a few sec­onds

* re­peat un­til the wax melts and every­thing is liq­uid

* let it cool down un­til the mix is solid

Brittle paste that’s hard to scoop from the jar and ap­ply on the wood. Doesn’t spread eas­ily, feels sticky.

After the whole wood sur­face was cov­ered and left for 10 min­utes, the ex­cess was wiped with a pa­per towel. After wip­ing, the fin­ish is very matte, which means that not much of the wax re­mained, and the oil did­n’t pen­e­trate the fiber enough be­cause of the con­sis­tency.

The con­sis­tency changes a lot based on the oil-to-wax ra­tio.

Too much wax and the blend cools into a brit­tle paste that’s very hard to scoop from the jar. Too lit­tle and the blend is too liq­uid with not enough wax re­main­ing on the wood sur­face to form a film. A 4:1 oil-to-wax ra­tio is good, hav­ing enough wax for the top layer, but in this sim­ple for­mu­la­tion it is still too hard and brit­tle.

Instead of in­creas­ing the oil quan­tity which could de­feat the pur­pose of the wax layer, I added a bit of beeswax to soften the blend.

This works, the paste be­comes softer but it makes the top layer of wax not durable enough be­cause of its low­ered melt­ing point, so I needed an al­ter­na­tive.

My idea is to have the wood ab­sorb the tung oil from the blend while leav­ing the wax mol­e­cules on the wood sur­face. The wax should be soft enough to not cre­ate a glossy layer and not be brit­tle, but hard enough to pro­tect the wood for the time it takes the tung oil to cure.

To soften the blend with­out hav­ing to add too much beeswax, I found lano­lin to be a good ad­di­tion. It is a highly hy­dropho­bic wax ex­tracted from sheep wool that even in tiny amounts can make the paste con­sis­tency softer and eas­ier to ap­ply.

Similar to #1, just im­merse the waxes into the oil in a glass jar and mi­crowave in in­cre­ments of 30 sec­onds un­til every­thing is liq­uid. Leave to cool un­til solid.

Softer and more ho­moge­nous paste that can be scooped eas­ily from the jar with a fin­ger or rag. Spreads rel­a­tively easy onto the wood sur­face, feels like a more vis­cous hand cream.

Smells amaz­ing, nutty, vanilla and honey scent, faint enough to not bother any­one.

After cov­er­ing the whole wood sur­face, I used a heat gun to liquify the fin­ish and en­hance wood fiber pen­e­tra­tion. The paste melts very eas­ily and the oil in it gets ab­sorbed quickly in the wood pores, leav­ing the wax to so­lid­ify.

After the wood has cooled, I ap­plied an­other layer be­cause it seemed that some parts of the wood had lit­tle to no wax re­main­ing. I re­moved the ex­cess with a pa­per towel and buffed the wax to a satin look.

This fin­ish is not fast cur­ing by any means. It is fast dry­ing, as the oil gets ab­sorbed and the wax on top so­lid­i­fies into a very thin medium-hard layer.

But the melt­ing point of the wax is about 75℃ (167°F) so still not per­fect for very hot liq­uids. You def­i­nitely can’t brew your tea di­rectly into a cup fin­ished this way, not un­til the oil cures com­pletely af­ter 2-4 weeks.

I tested it by brew­ing a cup of espresso which seems to be fine, the tem­per­a­ture of the cof­fee is far be­low 75℃ (167°F) when it reaches the cup.

Using a spoon for eat­ing soup also works fine, be­cause the soup needs to be be­low 45℃ (113°F) for me to be able to eat it.

After us­age, the wooden spoon and cup could be eas­ily washed with warm wa­ter and soap, the wood did­n’t stain at all. The wax still worked as I could see the wa­ter droplets slid­ing off the wood.

Visually, it does­n’t leave a very strong sheen. It has a soft waxy look, in­stead of the shim­mer of oiled wood.

That’s be­cause wax does­n’t fol­low the mi­cro porous sur­face of the wood, it so­lid­i­fies into a smooth sur­face. So in­stead of scat­ter­ing light you get mir­ror-like re­flec­tions cre­at­ing that glossy wax look.

Commercial fin­ishes use flat­ten­ing agents like fumed sil­ica to get around this, but I’m try­ing to use as lit­tle ad­di­tives as pos­si­ble for now.

The look also comes from the car­nauba wax be­ing soft­ened by the beeswax and lano­lin which also trans­lates into a softer top layer.

The wood­work­ing world has moved on al­most com­pletely from nat­ural resins. Almost every fin­ish is ei­ther based on polyurethane or epoxy resin if you’re look­ing for a harder top layer. At best, you’re look­ing at a shel­lac layer which does­n’t mix with oils.

Thankfully oil paint­ing fo­rums and blogs still have a trove of in­for­ma­tion on tree resins, dry­ing oils and sicca­tives.

That’s how I found out about damar resin, a semi-hard resin ex­tracted from Dipterocarpaceae trees grow­ing in south­east Asia. It is a clear resin, melts at about 120℃ (248°F) which is eas­ily at­tain­able in a mi­crowave, and has a bit of flex­i­bil­ity so that it does­n’t cre­ate a crack­ing layer on wood.

It can be found in the form of crys­tals or pel­lets in art shops and it’s pretty cheap. People dis­solve it in tur­pen­tine to cre­ate var­nishes, but I wanted to in­cor­po­rate it into my oil-wax blend through heat in­stead of sol­vents.

To in­crease sheen and make the top layer stronger, I melted damar resin crys­tals di­rectly into oil, with­out any sol­vent. I also added a very small amount of man­ganese, zir­co­nium and cal­cium drier to make the cur­ing faster, and some vi­t­a­min E to in­crease shelf life.

Add the car­nauba wax, beeswax and lano­lin into the tung oil in a glass jar and mi­crowave in in­cre­ments of 30 sec­onds un­til every­thing is liq­uid.

Add the damar resin crys­tals into the co­conut oil and mi­crowave in in­cre­ments of 10 sec­onds un­til every­thing is liq­uid. Let the mix cool down for about 30 sec­onds then add the drops of MnZrCa drier and vi­t­a­min E. Stir un­til the mix is ho­moge­nous.

Pour the damar resin-oil blend into the tung oil blend and stir un­til ho­moge­nous. Let cool down un­til solid.

Medium-soft paste that can be scooped rel­a­tively eas­ily from the jar with a fin­ger or rag. Spreads easy enough onto the wood sur­face.

Smells the same as the last ex­per­i­ment: nutty, vanilla and honey scent, faint enough to not bother any­one. The nasty smell of the drier does­n’t trans­fer into the blend be­cause its quan­tity is too small. The resin has no smell in its solid form.

After cov­er­ing the whole wood sur­face, I used a heat gun to liquify the fin­ish and en­hance wood fiber pen­e­tra­tion. The paste melts very eas­ily and the oil in it gets ab­sorbed quickly in the wood pores, leav­ing the wax and resin to so­lid­ify into a very thin layer on top.

After that there was al­most no ex­cess left and I buffed the top layer to a satin look us­ing a pa­per towel.

The tung oil in­side the wood cured in about 48 hours.

This can be ver­i­fied by melt­ing the wax layer with a heat gun then re­mov­ing the liq­uid wax with a rag. The bare wood then can be sanded with 240 grit to check if the wood dust falls off eas­ily. If the wood dust seems wet and gums on the sand­pa­per, the oil is still not com­pletely cured.

The satin sheen looks bet­ter be­cause of the resin. Regions with medullary rays look wavy and move in the light, re­gions with straight fibers look ex­actly be­tween glossy and matte.

Osmo Polyx Oil still has a pret­tier shim­mer that this fin­ish does­n’t achieve, I’ll look into adding trace amounts of fumed sil­ica to see if it makes the fin­ish set­tle bet­ter into the wood fiber mi­crostruc­ture and scat­ter light in­stead of be­ing more on the smooth glossy side.

The fumed sil­ica might also help with adding shear thin­ning ca­pa­bil­ity so that the paste is even eas­ier to scoop from the jar with­out soft­en­ing it.

The metal­lic dri­ers are prob­a­bly the first thing that jump out, be­cause we al­ways read about how bad they are when see­ing peo­ple talk about nat­ural wood fin­ishes. Not all dri­ers are bad, and it de­pends on things like quan­tity, leach­ing prob­a­bil­ity and type of metal used.

Sure, lead and cobalt dri­ers are out of the ques­tion, I don’t want them any­where near my food and bev­er­ages no mat­ter how small the risk of leach­ing. They con­tain heavy met­als that can have cat­a­strophic ef­fects if they ac­cu­mu­late in your body.

I use a drier con­tain­ing man­ganese neode­canoate to speed up sur­face-dry­ing, and zir­co­nium and cal­cium salts for through-dry­ing.

Zirconium and cal­cium are known to be safe. Zirconium is the same metal that den­tal im­plants are usu­ally made of, even ce­ramic knives are made us­ing zir­co­nium, it seems to be a pretty in­ert metal when it comes to con­tact with our body.

Manganese is toxic if in­haled or in­gested in high amounts, but the quan­tity of man­ganese in 2 drops of drier is so in­cred­i­bly low you could take them orally and not feel any ef­fect other than the hor­ri­ble sol­vent taste. That, com­bined with the fact that the drier dis­perses through­out the oil makes the quan­tity too low to mat­ter.

The strictest Tolerable Upper Intake Level for man­ganese is set to 8 mg/​day. In fact we get some of that quan­tity daily through food that is en­riched with vi­t­a­mins and min­er­als. If the drier were to ever leach com­pletely from the fin­ish, one would get less than 0.1mg per life­time of ob­ject.

You’d prob­a­bly have to eat the spoon com­pletely for that to hap­pen, in which case the quan­tity of in­gested wood might be­come more of a prob­lem.

But the whole food-safe stan­dard on drier based fin­ishes is ac­tu­ally based on the fact that a cured fin­ish traps that metal into an in­ert poly­mer which can’t leach into food. Just like Teflon pans or alu­minum and cop­per pots, every­thing is safe un­til the layer chips off some­how.

I com­pro­mised on hav­ing a quan­tity small enough to not pose any safety risk and that would­n’t shorten shelf life by mak­ing the oil cure in­side the jar, but high enough to make the oil cure in 48 hours in­stead of 2-4 weeks. This, in my opin­ion, makes the fin­ish safer by be­ing more pre­dictable in cur­ing time, and min­i­miz­ing the prob­a­bil­ity of food con­tact­ing un­cured tung oil.

Because damar resin melts at 120℃ (248°F), tung oil is not suit­able for melt­ing the resin di­rectly into it be­cause tung oil can gelify at high tem­per­a­tures, hin­der­ing its cur­ing ca­pa­bil­i­ties. That’s why I melt the resin crys­tals in a small amount of co­conut oil, which has a high enough smok­ing point of 180℃ (356°F), smells amaz­ing and does­n’t go ran­cid eas­ily.

...

Read the original on alinpanaitiu.com »

8 180 shares, 15 trendiness

Last.fm and Audioscrobbler Herald the Social Web

Following in Amazon’s foot­steps, two stu­dent pro­jects in­de­pen­dently use collaborative fil­ter­ing’ to bring rec­om­men­da­tions and so­cial net­work­ing to on­line mu­sic; soon they will join forces.

What we now know as the social web” — or Web 2.0 — did­n’t ar­rive un­til around 2004. But the first inklings of it were emerg­ing a cou­ple of years be­fore. As usual, mu­sic was the har­bin­ger.

Last.fm was founded in 2002 by a group of four Austrian and German stu­dents from Ravensbourne College of Design and Communication in London. It was fash­ioned as an in­ter­net ra­dio sta­tion that al­lowed a user to build a lis­ten­ing pro­file and share it with oth­ers. The year of its launch, Last.fm won a young tal­ent award at the Europrix, a mul­ti­me­dia awards show based in Vienna. This was how the prod­uct was de­scribed in a show­case video (embedded be­low) lead­ing up to the awards cer­e­mony:

After re­peated use, the sys­tem builds a lis­ten­ing pro­file that in­creas­ingly re­flects the user’s pref­er­ences. The sum of all pro­files is vi­su­al­ized in the Map of Music,’ a pre­sen­ta­tion of mu­si­cal con­nec­tions and gen­res de­ter­mined only by the col­lab­o­ra­tive ef­fort of Last.fm users.”

When the stu­dents went up to re­ceive their award, one of them, Thomas Willomitzer, noted the im­por­tance of collaborative fil­ter­ing” to the Last.fm sys­tem. The idea was that the Last.fm al­go­rithm would rec­om­mend mu­sic you might like, based on your lis­ten­ing his­tory com­bined with the lis­ten­ing his­tory of other, sim­i­lar, users. Willomitzer added that this type of al­go­rithm would be fa­mil­iar to peo­ple who used Amazon.com.

Here’s a video of the Last.fm founders pre­sent­ing at Europrix 2002, via Thomas Willomitzer:

Collaborative fil­ter­ing was a com­mon tech­nique in rec­om­mender sys­tems, and its his­tory dated back to be­fore the web — for in­stance, it was the ba­sis for a 1992 Xerox PARC email sys­tem called Tapestry.’ But col­lab­o­ra­tive fil­ter­ing re­ally came into its own dur­ing the web era, and in par­tic­u­lar it was pop­u­larised by Amazon. By 2002, Amazon users were fa­mil­iar with the fol­low­ing mes­sage: Customers who bought items in your Shopping Cart also bought…” There was also a Your Recommendations” list on the Amazon.com home­page. Both of these fea­tures were cre­ated us­ing an al­go­rithm that Amazon called item-to-item col­lab­o­ra­tive fil­ter­ing.” As ex­plained in a re­search pa­per:

Rather than match­ing the user to sim­i­lar cus­tomers, item-to-item col­lab­o­ra­tive fil­ter­ing matches each of the user’s pur­chased and rated items to sim­i­lar items, then com­bines those sim­i­lar items into a rec­om­men­da­tion list.”

Amazon col­lab­o­ra­tive fil­ter­ing ex­am­ples; via re­search pa­per by Greg Linden, Brent Smith and Jeremy York, pub­lished by the IEEE Computer Society in January-February 2003 edi­tion.

The key here is that Amazon’s col­lab­o­ra­tive fil­ter­ing was done based on the items peo­ple bought or rated, not the pro­files of its users. This ap­proach was also cru­cial to how new so­cial web ser­vices like Last.fm would de­velop. The map of mu­sic” that Last.fm cre­ated was all about map­ping which songs (or gen­res) were in­ter­con­nected — so a cer­tain Bob Dylan song might have a strong con­nec­tion to a cer­tain Joni Mitchell song, based on lis­tener data, and thus the Mitchell song might come up as a rec­om­men­da­tion for peo­ple who lis­tened to the Dylan song (and vice versa).

By co­in­ci­dence, an­other stu­dent in the UK was also work­ing on a rec­om­men­da­tion sys­tem for mu­sic in 2002. Audioscrobbler was started as a com­puter sci­ence pro­ject by Richard Jones at the University of Southampton. Jones coined the term audioscrobbling” (later short­ened to scrobbling”) to de­scribe the process of track­ing songs that you lis­ten to in or­der to make a lis­ten­ing pro­file, which is then used for rec­om­men­da­tions.

In an April 2003 in­ter­view with his University’s pa­per, twenty-year old Jones ex­plained how Audioscrobbler worked:

Users of the sys­tem need to down­load soft­ware on to their com­puter that mon­i­tors what artists they lis­ten to. The data is then col­lated and a pat­tern emerges by way of a tech­nique known as collaborative fil­ter­ing.’ The re­sults are then recorded against a user­name and can be com­pared with the lis­ten­ing tastes of other mem­bers.”

Later, Jones would team up with the Ravensbourne College stu­dents and fold his pro­ject into Last.fm, but even in 2002 — when they were in­de­pen­dent prod­ucts — it is strik­ing how sim­i­lar the two sys­tems were. Both used col­lab­o­ra­tive fil­ter­ing to cre­ate song rec­om­men­da­tions, and both aimed to cre­ate a kind of so­cial net­work based around what users lis­tened to.

The key to the emerg­ing so­cial web would be that you dis­cover new con­tent and com­mu­ni­ties by fol­low­ing other peo­ple. For mu­sic, the idea was to help you break away from the es­tab­lished broad­cast model. At the Europrix event, Last.fm’s Martin Stiksel brought out a 1980s-style tran­sis­tor ra­dio to il­lus­trate the point. If you want to lis­ten to mu­sic on such a de­vice, Stiksel ex­plained, you have to tune the fre­quency band to find your sta­tion. If you don’t like the mu­sic play­ing on that sta­tion, you tune the dial to an­other ra­dio sta­tion and try your luck again.

The in­her­ent prob­lem with broad­cast me­dia is that ba­si­cally, at the end of the day, it’s al­ways some­body else se­lect­ing the mu­sic for you,” said Stiksel. So there’s al­ways a bunch of ed­i­tors or pro­gram­mers that picked the mu­sic and put them into into a pro­gram for you.”

Three Last.fm founders in 2002 with a tran­sis­ter ra­dio, from the 80s, I be­lieve.”

With Last.fm, the stream of mu­sic you heard was a mix of man­ual choice and al­go­rith­mic se­lec­tion. You might start with a song al­ready in your on­line record col­lec­tion” (the term Stiksel kept us­ing), or start from an­other user’s pro­file. From then on, songs would be cho­sen for you based on col­lab­o­ra­tive fil­ter­ing. If you played a song through, the Last.fm soft­ware au­to­mat­i­cally added it to your own col­lec­tion. You could also press a love” but­ton to add it. But if you did­n’t like a cer­tain track, you could press a hate” but­ton (so it would­n’t get played again), or click the skip” but­ton to move to the next song. There was also a change” but­ton to go to a dif­fer­ent user pro­file.

The early Last.fm user in­ter­face was, in truth, a bit clut­tered with all these dif­fer­ent but­tons and var­i­ous search boxes — but over time it would get more stream­lined.

Stiksel ex­plained that the idea for Last.fm came about when the stu­dents asked them­selves, how do you look for some­thing that you don’t know?” So in the case of mu­sic, how to dis­cover new mu­sic when you don’t nec­es­sar­ily know what type of mu­sic you’re look­ing for? The an­swer, he said, was the so­cial com­po­nent.

Then we fig­ured out that it’s the so­cial as­pect of mu­sic — the best mu­sic you al­ways find when you go to your friend’s house and he plays you records. And we’re tak­ing this con­cept into an on­line en­vi­ron­ment here.”

What both Last.fm and Audioscrobbler stum­bled onto in 2002 was the col­lec­tive value of user data in dis­cov­er­ing new con­tent — some­thing that Amazon was also tak­ing ad­van­tage of at this time. The prob­lem with mu­sic, though, was that li­cens­ing from record com­pa­nies was still highly re­stric­tive. The Last.fm founders some­what glossed over it dur­ing their Europrix pre­sen­ta­tion, but they did ad­mit that due to le­gal is­sues, we’re only al­lowed to play 30 sec­ond sam­ples.” Unless you al­ready owned a piece of mu­sic, 30 sec­onds was all you got.

By the fol­low­ing year, how­ever, Last.fm had be­gun turn­ing it­self into an online ra­dio” ser­vice, by pay­ing li­cens­ing fees to the UK col­lect­ing so­ci­eties PRS (Performing Right Society) and MCPS (Mechanical-Copyright Protection Society).

So pre-Web 2.0, the stream­ing rev­o­lu­tion was only just get­ting started. But with Last.fm and Audioscrobbler, we at least glimpsed the fu­ture of the so­cial web.

Last.fm in August 2006. This is the de­sign we now re­mem­ber, but it took sev­eral years to get there. Via Wayback Machine.

Cybercultural is a weekly on­line mag­a­zine about in­ter­net his­tory and its cul­tural im­pact. Subscribe:

My Web 2.0 mem­oir, Bubble Blog: From Outsider to Insider in Silicon Valley’s Web 2.0 Revolution, is now avail­able to pur­chase:

Or search for Bubble Blog MacManus” on your lo­cal on­line book­store.

...

Read the original on cybercultural.com »

9 149 shares, 6 trendiness

Dan Piponi (@dpiponi@mathstodon.xyz)

To use the Mastodon web ap­pli­ca­tion, please en­able JavaScript. Alternatively, try one of the na­tive apps for Mastodon for your plat­form.

...

Read the original on mathstodon.xyz »

10 147 shares, 9 trendiness

iOS 26.2 Fixes 20+ Security Vulnerabilities

Apple to­day re­leased iOS 26.2, iPa­dOS 26.2, and ma­cOS 26.2, all of which in­tro­duce new fea­tures, bug fixes, and se­cu­rity im­prove­ments. Apple says that the up­dates ad­dress over 20 vul­ner­a­bil­i­ties, in­clud­ing two bugs that are known to have been ac­tively ex­ploited.

There are a pair of WebKit vul­ner­a­bil­i­ties that could al­low ma­li­ciously crafted web con­tent to ex­e­cute code or cause mem­ory cor­rup­tion. Apple says that the bugs might have been ex­ploited in an at­tack against tar­geted in­di­vid­u­als on ver­sions of iOS be­fore iOS 26.

Processing ma­li­ciously crafted web con­tent may lead to ar­bi­trary code ex­e­cu­tion. Apple is aware of a re­port that this is­sue may have been ex­ploited in an ex­tremely so­phis­ti­cated at­tack against spe­cific tar­geted in­di­vid­u­als on ver­sions of iOS be­fore iOS 26.

Processing ma­li­ciously crafted web con­tent may lead to mem­ory cor­rup­tion. Apple is aware of a re­port that this is­sue may have been ex­ploited in an ex­tremely so­phis­ti­cated at­tack against spe­cific tar­geted in­di­vid­u­als on ver­sions of iOS be­fore iOS 26.

One of the WebKit bugs was fixed with im­proved mem­ory man­age­ment, while the other was ad­dressed with im­proved val­i­da­tion.

There are sev­eral other vul­ner­a­bil­i­ties that were fixed too, across apps and ser­vices. An App Store bug could al­low users to ac­cess sen­si­tive pay­ment to­kens, pro­cess­ing a ma­li­cious im­age file could lead to mem­ory cor­rup­tion, pho­tos in the Hidden Album could be viewed with­out au­then­ti­ca­tion, and pass­words could be un­in­ten­tion­ally re­moved when re­motely con­trol­ling a de­vice with FaceTime.

Now that these vul­ner­a­bil­i­ties have been pub­li­cized by Apple, even those that were not ex­ploited be­fore might be taken ad­van­tage of now. Apple rec­om­mends all users up­date their de­vices to iOS 26.2, iPa­dOS 26.2, and ma­cOS Tahoe 26.2 as soon as pos­si­ble.

...

Read the original on www.macrumors.com »

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.

If you like 10HN please leave feedback and share

Visit pancik.com for more.