You shouldn’t. What happens is that you implement a minimal feature set to get your website working. Then, next time you want to add something to the website, you realize a necessary feature is missing, and instead of updating the website, you spend your time implementing the feature. This happens over and over again and you lose interest in updating the website because it’s so much work every time.
Last time I tried, I found that even choosing a static site generator from the seemingly infinite list of options in 2016 was arguably more work than just building one. We tacked on a build pipeline for images and javascript at some point, but other than that I don’t think any features were added during the life of the site. There are certainly features it didn’t have, but that’s just the power of knowing your requirements up front, I guess.
Not to mention keeping your 3rd party SSG up to date. “Oh, I can’t post to my blog because _____ isn’t compatible with the current version of Ruby/Python/etc. Guess I’ll update it. Oh, now it’s obsoleted some config options I’m using, better learn what the modern equivalent is. Oh, looks like the theme I installed isn’t compatible, is there an updated version? No? Time to look for a new theme. Oh, now I remember I patched the old theme to add a custom feature and my pages won’t render without it; how do I port that patch to the new theme? Wow, looks like the theme engine changed a lot, I don’t recognize half these tags…”
The SSG doesn’t interact with the internet or any kind of untrusted data. Hence it’s totally fine to keep a VM or container image with the old working version of the tools forever and never update anything. :)
100% - I tried to get something done and was looking at hugo after a few years and it was quicker to write my own before reading up and making it work.
I’m not sure it’s fair to make a generalization about this. I found that building my own blog (not actually a SSG) in Rust with Axum and Maud was actually quite comfortable and ergonomic since I was able to lean on the existing tools that exist (Tower for any HTTP stuff, Comrak for markdown parsing etc).
It was a fun learning experience, and I think a blog is simple enough to be doable as a learning exercise, but complex enough to expose you to a lot of language features you might otherwise have missed.
My experience with using an off the shelf SSG is that everything was fine and dandy until I wanted to do something I felt was pretty basic but which I ended up spending hours and hours on trying to get to work before finally giving up. Writing my own would not have this problem. I would just implement the basic features I actually need and then not touch it again.
This isn’t limited to homemade SSGs though. I’ve had to write quite a bit of Ruby and understand Jekyll internals to get some plugins to work together and in the way I want them to work, and the solutions feel rather hacky and are verbose liquid templates. I’m fairly certain this takes less time than making my own SSG, but from experience it’s much less fun than making it yourself.
And if you want a feature that’s not yet supported in some SSGs like e.g. Hugo, you’re stuck because there’s no plugin system at all.
I don’t think this is the case for everyone. I’m sure there are edge cases, but if you simply need your SSG to render posts/pages/RSS you will be fine. The average “simple” blog rarely needs new features.
Yeah I’ve had my own custom blog site since 2008 and this has never happened to be once. If anything I’ve removed features I realized were unnecessary.
But it’s fun work. At least for me, as I don’t work in the web world normally. I wrote my own blog engine and over the 24 year history of my blog, there have been features I’ve added (like automatically cross posting to InstaMyFaceMePinTikLinkedSpaceTotWeBookGramTrestIn) only to remove later (when the API inevitably change). I’m not worried about the language it’s written in changing too much, as it’s in C.
In contrast, the rest of my website is a static site, using xsltproc (quite the retro-future approach). I wrote the XSLT back (as far as I can tell) around 2003-2004 and there was only one time I had to update it due to changes in xsltproc. I do not recommend using XSLT—it works, but boy, is it verbose. Way more than Cobol (and it’s a pure functional language, which is even more head exploding).
What happens is that you implement a minimal feature set to get your website working
FWIW I did exactly that for https://www.oilshell.org/ . I wrote a shell script that used Gruber’s markdown.pl (packaged in Debian) to put up a single blog post, and then an index.html that linked to it.
People actually read and liked the blog, which I was slightly surprised by, given that I knew many people had “written off” shell as a language to be learned.
So now I knew it was worth spending some time on, and gradually added features over the years. The anti-pattern is to “plan” the blog up front.
Then, next time you want to add something to the website, you realize a necessary feature is missing, and instead of updating the website, you spend your time implementing the feature. This happens over and over again and you lose interest in updating the website because it’s so much work every time.
That didn’t happen in my case. It’s not too much effort to use shell and Python to add new features.
It may not look like it, but the site is pretty deep now
I also deleted Google analytics a few years ago, and now use a pipeline of Python + R + JS + shell to make my own graphs. (the thing that is rotting here is the spam detection – there are so many undeclared crawlers these days)
It also has topic tagging, and OpenGraph metadata for Twitter/Mastodon etc.
I would say that if it were only Python, it would be too much work. I would maybe have given up on doing everything myself.
I would have fallen into the “programmer blogger trap”. This kind of code can be very repetitive and non-composable in pure Python.
But gluing everything together with shell makes it feasible. It’s just less code overall. And it’s faster to iterate.
I mentioned this Unix philosophy / multi-language / multi-process factoring here:
And to be fair it took me a long time to build up those skills – making a website is not trivial !!! I failed to make websites from scratch before, for sure. Multiple times. The benefit has to be worth the effort, as you say, and the effort is often high.
But now that I finally have one, I view it as an asset.
This of course also applies to most anyone using full-disk encryption on Linux. This piece is Tails-specific, but some articles about LUKS params made the rounds some months ago as well.
I often find myself wishing there was a common monitoring tool LIKE a log, but explicitly designed for being machine readable. Rather than being a trace of program execution (which can and should change in new versions of the program), it would be a specific event notification with a code and arguments that was part of the program contract that could be handled by observability tooling. While there are some efforts in that direction with structured logging, tracing, metrics, etc., none of them are really doing this.
You may enjoy https://www.honeycomb.io/ approach which is basically what you described. (They’re heavily doing events-not-logs) Alternatively, Datadog events are basically message + tags, so should cover most of it. Grayling also does logging as GELF structures events and you can treat them as events.
(This doesn’t directly match what you’re asking for but it’s relevant.)
I saw a blog post a while back (wish I could figure out how to dig it up!) that advocated for abandoning logs and instead having code produce well-structured events that could be subscribed to as a stream. And yes, those could be streamed to a text format but they would be first and foremost a well-defined output of a particular module.
It’s a neat vision and I’ve actually used that approach in at least one bit of code.
This is the convenience argument made in a nutshell for appending to native prototypes:
…it’s not chainable like other array methods and you need intermediate variables…
I was a fan of Sugar.js a decade ago. I loved the idea of a rich, sugary, chainable, “standard” library for JavaScript. But I learned the hard way you shouldn’t modify objects you don’t own for all the reasons you described. This symbol-based solution, though novel in how it tackles the previous way people have been burned, creates new ones. Specifically, in an era where JavaScript codebases get a bad rep for being bloated and needlessly complicated, how would one cherry-pick only the needed methods of a library written this way? Assuming there was a way to cherry-pick, how would ambient typing work so as to reflect the selected methods? Or de-duping of multiple, cherry-picked instances of the same library in upstream dependencies?
Another implicit convenience of libraries like Prototype.js or Sugar.js was that you didn’t have to wonder whether some needed function was in scope. Once the methods were added, they were everywhere. This was especially handy in debugging contexts. Accessing methods by symbol requires that you have the symbols at hand.
I suppose you could set up separate modules in the same package for each method and then an umbrella module at the root of the package for folks who wanted all of them. I guess each of the modules could have their own .d.ts file for ambient types. It would be amazing if all of that actually worked with the major build tools and runtimes.
Having to explicitly import the methods used is an upside, not a downside, because that was a criticism of extending natives that you just had to know what methods existed. Nothing else mentioned is actually specific to this approach, because any helper library could have duplicate versions, and tree-shaking or types work fine, as the PoC shows.
…it’s not chainable like other array methods and you need intermediate variables…
Having written in Clojure for about a decade, my reaction to this was “???”. This is exactly how things work in functional languages and it doesn’t cause a problem.
Clojure has the highly idiomatic ->>, and let expressions. JavaScript has neither, pipe is not idiomatic, and doesn’t play as nice with typescript as chaining.
Software is no different than any other artifact in life which can be misused. As human knowledge and intelligence progresses through time, these artifacts will only increase in number and so will their abuse or misuse.
Arguably, if guns weren’t invented many centuries ago, we would all be living in so much peace and security without all those malicious acts? And nukes were also misused so much, look what happened in Hiroshima and Nagasaki and still the threat hasn’t gone? And don’t even get me started on the misuse of political and legal systems! How is misuse of software different from any other kind of abuse or miuse?
I think that you missed the point of the exercise. It isn’t about declaring that all software engineering is dangerous, but about reflecting on the things that you’ve already built and released into the world. What effects do your tools have?
Your and my tools become the community’s tools once they are open source, they are no different than anything else available in the public domain. If you go back and ask Newton, “Hey, what effects do you think your atomic thingy will have on this world?”, what answer do you think he’d give? Should he be forced to stop all development and tooling to ensure that no Hiroshima gets hit? That will also ensure that we never get to travel in air or go to space.
The tl;dr is that PEP 668 provides a mechanism – a specially-named sentinel file at a particular location – to declare a Python installation/environment as “externally-managed” (its packages are installed and updated via some non-pip package manager, such as apt). Recent versions of pip respect this and will refuse to install packages into such an “externally-managed” Python environment.
Debian are marking their default system Python as “externally managed”, so any workflows on any Debian-based distros which assumed the ability to do a pip install with the system Python will be broken and will have to either switch to using apt to install the desired packages, or create and use a Python virtual environment to pip install into.
Posting this today because Ubuntu 23.04 has been out for a few days and people are apparently tripping over this as they upgrade to it.
(I am and long have been on Team Use A Venv, Always, Yes, Even In A Container, Really” and recommend you join us)
so any workflows on any Debian-based distros which assumed the ability to do a pip install with the system Python will be broken
From my experience, this was already broken in practice. The moment you did that on a Debian box the python situation was so messed up you could rather reinstall than try to fix it.
It’s going to be a problem mostly for Debian-based containers, where you treat the system Python as your environment (for good reason - you’ll never upgrade afterwards anyway).
As specified in the PEP, the process for a compliant installer is that if it detects it’s not running in a venv and it finds the EXTERNALLY-MANAGED sentinel file at the correct location, it’s supposed to instantly bail out and display an error message (and the sentinel file can provide the error message to display).
It’s a weird state that system python’s have to be there (for the system) but are effectively always too broken to use (same on macOS and even with Homebrew).
When you do an April Fools joke and everyone’s reaction is ‘Hurray! Oh, it’s a joke, never mind’, that might be a clue that you’re going down the wrong path.
Check out that timeline. Microsoft fixed the vulnerability for Bing immediately… and then failed to proactively check for the same kind of mistake on any of their other applications. It was only when the researcher reported the results of their own scans 3+ weeks later that Microsoft took broader action.
This is an important lesson: If you made the mistake in one place, you probably made it elsewhere too. Look for other instances of the same problem.
Microsoft got extremely lucky, here. $40k is not too shabby, but learning this the hard way would have cost tens of millions.
And if your backend has to expect traffic from, say, curl, or whatever, then you might as well acknowledge that fact fundamentally and say arbitrary JS scripts out there can also hit the endpoint
If you’re asking this question, that means you haven’t understood the idea behind CORS. :-) As far as I am aware, nothing aside from a browser even gives the CORS headers a second glance. They don’t do anything in and of themselves; they are purely instructions to a browser to say “here’s how these sites can interact”.
“A way to relax the same-origin policy” is indeed correct. The thing to keep in mind though is that the SOP is purely a concept in browser-land. Nothing else cares about it.
SQL injection is solved - in theory - by escaping inputs properly or better by prepared queries. Of course it’s been a hugely disappointing disaster trying to get practice to keep up. Anyway..
There seems to be no way to correctly prevent prompt injection, is there? You can push the probability down by adding more guard rules to the prompts, but I don’t trust that.
Perhaps a multi-modal version needs to be trained, with a system prompt completely separate from the user input? I really don’t know if that would even help. Who knows?
If it were transforming trees, or structured text, then quotation marks would not just suggest an inner block of text, but denote a hard barrier between outer and inner context.
At that point, the problem shifts to prompt engineering again, since the prompt must direct the transformer to use the quotation blocks when appropriate.
I don’t understand LLMs really, but ISTM they lex stuff into tokens, right? Couldn’t you make up a token that is deliberately excluded from the semantics of the universe and then use it as a barrier? Essentially, the fnord solution.
There are at least two special tokens present in the training process of these systems to mark the start and the end of the text. There is no way for a human to type these two tokens into the prompt, because no utf-8 sequence of characters would produce them.
Introducing a third special token (or however many) and using it as a separator could prove very effective at avoiding prompt injection. The main challenge here is that the network would have to be retrained (or at least fine-tuned) to understand the semantics of this new token, and training data adjusted to use it consistently.
Yes, it would need to be added in at the very beginning of the process. All of these prompt jailbreaks come by overcoming the late additions that are either fine tuned or worse just one shot learning.
I’ve had some decent results by block-quoting the user input in a prompt, but nothing definitive. I think the only safe solution here is to treat the LLM output as unsanitized user input, and not eval it in a trusted environment.
I think it’s interesting how comparatively few words humans need to encounter in childhood to reach the level of intelligence they develop. Either the brain is far more powerful than any computer system we have, our learning algorithms are far below the level of efficiency they could achieve, other human sensory stimuli fill in the gap, or the brain is not a computer. The last one seems hard to believe but as seems popular to point out, humans love believing the technology du jour (the wheel, books, mechanical systems, now computers) to be the true nature of reality. Brains could be an entirely new category of technology beyond computers we have yet to develop or conceive.
LLMs have, to a close approximation, read every word ever written by humans. That isn’t close to true of even the greatest geniuses our species has produced.
If you want to continue the rabbit hole of brains being an entirely new kind of technology, you may be interested in this post:
Imagine a flashy spaceship lands in your backyard. The door opens and you are invited to investigate everything to see what you can learn. The technology is clearly millions of years beyond what we can make.
My understanding is that the process of training a LLM on a (very) large collection of text is not at all like a person reading. The current LLMs are super impressive and surprising but they have taken a different path from human cognition.
There is a relatively big community of AI researchers who explore techniques to make learning a lot more efficient. This book provides a nice CS-oriented summary [1].
In a nutshell, humans are very good at building abstractions using hierarchies and mixtures of concepts. These map quite nicely to the eponymous models in statistics.
I suspect our brains come with a certain amount of implicit knowledge built in and just need to connect it to words. (How else could you communicate the concept of “thoughts” to a child?) This wouldn’t explain everything, but it would give us a head start.
I suspect our brains come with a certain amount of implicit knowledge built in and just need to connect it to words.
There’s some pretty famous research that was done in remote parts of (at the time) the USSR with people who were not and never had been literate, and which established some fascinating things about the changes in our thinking literacy – even slight literacy – produces. One of which is the concept of words as things, and as things that can be reasoned about, have things predicated of them, and so on. You almost certainly take that and many other similar abstract-concepts-as-things for granted, but you were not born with them.
(if you want to dig more into this, read up on Walter Ong – his work, or even just a good summary or any good bibliography will turn up more things to read on the subject)
Literacy is another topic entirely, although I’m sure it does have dramatic effects on the brain. I’m talking about how the developing brain connects the concept of heavy with the spoken word “heavy”, or the idea of being helpful with the word “help”. Parents chattering at children (describing their behavior to them) and children being little sponges is critical, but I suspect there’s also a pre-built set of templates that are waiting for words to match up to.
Visual sensory input is absurdly high bandwidth compared to text. It’s not surprising that it takes a large amount of text to reach comprehension. If anything, it’s amazing how little input is needed. I suspect this is because text input is relatively high entropy (i.e. information density) compared to vision.
GPT4 is trained on both text and images, and shows considerably improved comprehension. Most likely, adding video and audio input would have a similar affect, although the computational demands would be much, much higher.
Fair point. Touch, too, is much higher bandwidth than text. But also much lower information density. Smell and taste are less clear.
Edit: but also agree with others that there is some built-in bias (via evolution) on what humans can efficiently learn. Just as there is some built-in bias of what any given artificial neural network architecture can efficiently learn.
This seems like a good pattern with an utterly terrible name. I’m never going to use or remember that name, because it doesn’t make sense to me even now, having just read an explanation of it!
Even just “agile cutover” (to make up a term) would be a better name.
3 years ago OpenBSD entirely removed TIOCSTI[2], Android has had it filtered for longer[3], and the tools that
had historically used TIOCSTI either do not need it, are not commonly built with it, or have had its use removed.
Between the dually analogized name Steel Threads and the following description:
With a Steel Thread approach, you build the thinnest possible version that crosses the boundaries of the system and covers an important use case.
followed by Step 1 from the example:
Think about the new system you’re building. Come up with some narrow use cases that represent Steel Threads of the system – they cover useful functionality into the system, but don’t handle all use cases, or are constrained in some ways.
I’m left wondering what I’m doing in step 1? Am I defining a thinnest possible version of something that crosses some boundaries of a system that constitutes one important use case? What does that mean?
I am left with so many more questions.
How does one define thinness?
What is a “thinnest possible version” a version of? A use case? If so, what is a version of a use case?
What is the unuseful functionality in a system that sets the “useful functionality” distinctly apart?
Is a “use case” always a useful version? Are versions a different word for use cases?
Are there thin versions that don’t cross system boundaries?
I’m not pooh-poohing on the concept. I’ve used the development pattern that I think Steel Threads attempts to describe, and I don’t think the name Steel Threads is useful or descriptive. What I’m hearing described is more of a development pattern mixed with a release strategy, and “steel threads” makes it sound like a specific tool or implementation detail. I understand why Wikipedia removed the article.
It’s indeed sad that this thread is dominated by hot-take reactions to the word “telemetry” mostly bringing up points already addressed by two long, thoughtful, evenhanded TFAs. I expected better, lobsters.
read the proposal, and still don’t want google to open this can of worms. what’s your point?
specifically, I don’t like how google will now include machinery to automatically phone home. I don’t have a problem with the current plans, especially that it’s now opt-in, but I have a problem with the idea that it will be very very hard for future google to ignore that they can now siphon data from anyone running Go apps. today it’s “anonymous, random” stuff, tomorrow it’s…. ?
My point is just that there are a lot of people who clearly haven’t read the proposal and who are invoking things like “but GDPR!” and “oh no, they’ll be able to build usage patterns”. (Not just here in this discussion page.) They clearly haven’t looked at the proposed mechanisms and the great care they would take to keep identifiable and invasive information out of the reports. It’s not perfect—there are changes I would make—but it’s better than many of the accusations being leveled against it.
Some people are instead just objecting on the basis of “Google is trying to slurp up information”. (In fact, while Golang came from Google and is still moderately associated with it, this isn’t Google per se, although I understand that that perception is real.) And that might be an OK objection if they used correct information, but most aren’t. I think if you want to object on that basis, you have to make a reasonable comparison with the current state of things. The Go team could try to do a frog-boil and start with innocuous telemetry and later start sneaking in some more invasive stuff, but… let’s be honest, we’ve got a community of detail-oriented nerds with strong opinions here. I don’t think it would work! And maybe they’d push it through anyway, but they could already do that today.
Honestly, it’s just very unfortunate that Go is the project bringing this proposal forward. I think that if a Python linter proposed this, the discussion would be going very differently. (And then depending on how that turned out, the Go folks could decide to adopt the same thing.) Someone has to pioneer privacy-preserving telemetry so that we can then go to existing projects and say “hey, use this instead”. Anything Google-associated is kind of doomed, though.
You shouldn’t. What happens is that you implement a minimal feature set to get your website working. Then, next time you want to add something to the website, you realize a necessary feature is missing, and instead of updating the website, you spend your time implementing the feature. This happens over and over again and you lose interest in updating the website because it’s so much work every time.
Last time I tried, I found that even choosing a static site generator from the seemingly infinite list of options in 2016 was arguably more work than just building one. We tacked on a build pipeline for images and javascript at some point, but other than that I don’t think any features were added during the life of the site. There are certainly features it didn’t have, but that’s just the power of knowing your requirements up front, I guess.
Not to mention keeping your 3rd party SSG up to date. “Oh, I can’t post to my blog because _____ isn’t compatible with the current version of Ruby/Python/etc. Guess I’ll update it. Oh, now it’s obsoleted some config options I’m using, better learn what the modern equivalent is. Oh, looks like the theme I installed isn’t compatible, is there an updated version? No? Time to look for a new theme. Oh, now I remember I patched the old theme to add a custom feature and my pages won’t render without it; how do I port that patch to the new theme? Wow, looks like the theme engine changed a lot, I don’t recognize half these tags…”
I’ve been down that road several times.
The SSG doesn’t interact with the internet or any kind of untrusted data. Hence it’s totally fine to keep a VM or container image with the old working version of the tools forever and never update anything. :)
An advantage of a statically compiled SSG is you can just keep the binary around forever.
Sure, but that’s a bit inflexible.
I’d much rather have the whole compiler environment snapshotted in a container or VM image because then I can make changes to the SSG.
100% - I tried to get something done and was looking at hugo after a few years and it was quicker to write my own before reading up and making it work.
I’m not sure it’s fair to make a generalization about this. I found that building my own blog (not actually a SSG) in Rust with Axum and Maud was actually quite comfortable and ergonomic since I was able to lean on the existing tools that exist (Tower for any HTTP stuff, Comrak for markdown parsing etc). It was a fun learning experience, and I think a blog is simple enough to be doable as a learning exercise, but complex enough to expose you to a lot of language features you might otherwise have missed.
My experience with using an off the shelf SSG is that everything was fine and dandy until I wanted to do something I felt was pretty basic but which I ended up spending hours and hours on trying to get to work before finally giving up. Writing my own would not have this problem. I would just implement the basic features I actually need and then not touch it again.
This isn’t limited to homemade SSGs though. I’ve had to write quite a bit of Ruby and understand Jekyll internals to get some plugins to work together and in the way I want them to work, and the solutions feel rather hacky and are verbose liquid templates. I’m fairly certain this takes less time than making my own SSG, but from experience it’s much less fun than making it yourself.
And if you want a feature that’s not yet supported in some SSGs like e.g. Hugo, you’re stuck because there’s no plugin system at all.
I don’t think this is the case for everyone. I’m sure there are edge cases, but if you simply need your SSG to render posts/pages/RSS you will be fine. The average “simple” blog rarely needs new features.
Yeah I’ve had my own custom blog site since 2008 and this has never happened to be once. If anything I’ve removed features I realized were unnecessary.
But it’s fun work. At least for me, as I don’t work in the web world normally. I wrote my own blog engine and over the 24 year history of my blog, there have been features I’ve added (like automatically cross posting to InstaMyFaceMePinTikLinkedSpaceTotWeBookGramTrestIn) only to remove later (when the API inevitably change). I’m not worried about the language it’s written in changing too much, as it’s in C.
In contrast, the rest of my website is a static site, using
xsltproc
(quite the retro-future approach). I wrote theXSLT
back (as far as I can tell) around 2003-2004 and there was only one time I had to update it due to changes inxsltproc
. I do not recommend usingXSLT
—it works, but boy, is it verbose. Way more than Cobol (and it’s a pure functional language, which is even more head exploding).FWIW I did exactly that for https://www.oilshell.org/ . I wrote a shell script that used Gruber’s markdown.pl (packaged in Debian) to put up a single blog post, and then an
index.html
that linked to it.People actually read and liked the blog, which I was slightly surprised by, given that I knew many people had “written off” shell as a language to be learned.
So now I knew it was worth spending some time on, and gradually added features over the years. The anti-pattern is to “plan” the blog up front.
That didn’t happen in my case. It’s not too much effort to use shell and Python to add new features.
It may not look like it, but the site is pretty deep now
I rewrote the TOC generator once (it used to be JS, and is now static) - e.g. the yellow box http://www.oilshell.org/blog/2023/06/narrow-waist.html
I wrote a separate Flask + JS tool to make these little story link boxes, and then I copy and paste into Markdown - http://www.oilshell.org/blog/2023/06/narrow-waist.html#appendix-blog-backlog
I wrote a separate tool in PHP to serve resized images, to save bandwidth - http://www.oilshell.org/blog/2023/06/surrogate-pair.html
I also deleted Google analytics a few years ago, and now use a pipeline of Python + R + JS + shell to make my own graphs. (the thing that is rotting here is the spam detection – there are so many undeclared crawlers these days)
It also has topic tagging, and OpenGraph metadata for Twitter/Mastodon etc.
I would say that if it were only Python, it would be too much work. I would maybe have given up on doing everything myself.
I would have fallen into the “programmer blogger trap”. This kind of code can be very repetitive and non-composable in pure Python.
But gluing everything together with shell makes it feasible. It’s just less code overall. And it’s faster to iterate.
I mentioned this Unix philosophy / multi-language / multi-process factoring here:
https://lobste.rs/s/r2jawd/avoid_load_bearing_shell_scripts#c_xelmvc
And to be fair it took me a long time to build up those skills – making a website is not trivial !!! I failed to make websites from scratch before, for sure. Multiple times. The benefit has to be worth the effort, as you say, and the effort is often high.
But now that I finally have one, I view it as an asset.
Except this also happens with SSGs you didn’t write, and then it’s even harder.
This of course also applies to most anyone using full-disk encryption on Linux. This piece is Tails-specific, but some articles about LUKS params made the rounds some months ago as well.
I often find myself wishing there was a common monitoring tool LIKE a log, but explicitly designed for being machine readable. Rather than being a trace of program execution (which can and should change in new versions of the program), it would be a specific event notification with a code and arguments that was part of the program contract that could be handled by observability tooling. While there are some efforts in that direction with structured logging, tracing, metrics, etc., none of them are really doing this.
You may enjoy https://www.honeycomb.io/ approach which is basically what you described. (They’re heavily doing events-not-logs) Alternatively, Datadog events are basically message + tags, so should cover most of it. Grayling also does logging as GELF structures events and you can treat them as events.
(This doesn’t directly match what you’re asking for but it’s relevant.)
I saw a blog post a while back (wish I could figure out how to dig it up!) that advocated for abandoning logs and instead having code produce well-structured events that could be subscribed to as a stream. And yes, those could be streamed to a text format but they would be first and foremost a well-defined output of a particular module.
It’s a neat vision and I’ve actually used that approach in at least one bit of code.
Wow, I had to turn off Javascript for this site. Horribly distracting animations and scroll effects… and pretty CPU-greedy, too.
This is the convenience argument made in a nutshell for appending to native prototypes:
I was a fan of Sugar.js a decade ago. I loved the idea of a rich, sugary, chainable, “standard” library for JavaScript. But I learned the hard way you shouldn’t modify objects you don’t own for all the reasons you described. This symbol-based solution, though novel in how it tackles the previous way people have been burned, creates new ones. Specifically, in an era where JavaScript codebases get a bad rep for being bloated and needlessly complicated, how would one cherry-pick only the needed methods of a library written this way? Assuming there was a way to cherry-pick, how would ambient typing work so as to reflect the selected methods? Or de-duping of multiple, cherry-picked instances of the same library in upstream dependencies?
Another implicit convenience of libraries like Prototype.js or Sugar.js was that you didn’t have to wonder whether some needed function was in scope. Once the methods were added, they were everywhere. This was especially handy in debugging contexts. Accessing methods by symbol requires that you have the symbols at hand.
Tree shaking symbols-related code seems doable
Unlike conventional monkey patching, with symbols both the monkey patching & usage of the new monkey patched method needs to reference the symbol
So if your code doesn’t call a function that references the symbol, or use the symbol directly, you could remove the the monkey patching code.
Edit: updated first sentence to be more clear
I suppose you could set up separate modules in the same package for each method and then an umbrella module at the root of the package for folks who wanted all of them. I guess each of the modules could have their own
.d.ts
file for ambient types. It would be amazing if all of that actually worked with the major build tools and runtimes.How? The whole point of symbols is that you can’t forge them or retrieve them.
Having to explicitly import the methods used is an upside, not a downside, because that was a criticism of extending natives that you just had to know what methods existed. Nothing else mentioned is actually specific to this approach, because any helper library could have duplicate versions, and tree-shaking or types work fine, as the PoC shows.
Sorry, I missed the PoC. I look forward to playing with it. Thanks for sharing!
Having written in Clojure for about a decade, my reaction to this was “???”. This is exactly how things work in functional languages and it doesn’t cause a problem.
Clojure has the highly idiomatic ->>, and let expressions. JavaScript has neither, pipe is not idiomatic, and doesn’t play as nice with typescript as chaining.
I feel like this might work better as a Typescript syntax extension.
I’m writing what is fundamentally communication software.
Communication can be used to organize or implement bad things.
Software is no different than any other artifact in life which can be misused. As human knowledge and intelligence progresses through time, these artifacts will only increase in number and so will their abuse or misuse.
Arguably, if guns weren’t invented many centuries ago, we would all be living in so much peace and security without all those malicious acts? And nukes were also misused so much, look what happened in Hiroshima and Nagasaki and still the threat hasn’t gone? And don’t even get me started on the misuse of political and legal systems! How is misuse of software different from any other kind of abuse or miuse?
I think that you missed the point of the exercise. It isn’t about declaring that all software engineering is dangerous, but about reflecting on the things that you’ve already built and released into the world. What effects do your tools have?
(I’m glad someone has caught on that Fun Format Fridays are supposed to be a fun philosophical sandbox.)
It’s worth thinking beyond malice too, though. My software journaling software isn’t very abuse prone, but it’s very fuck-up prone…
Your and my tools become the community’s tools once they are open source, they are no different than anything else available in the public domain. If you go back and ask Newton, “Hey, what effects do you think your atomic thingy will have on this world?”, what answer do you think he’d give? Should he be forced to stop all development and tooling to ensure that no Hiroshima gets hit? That will also ensure that we never get to travel in air or go to space.
Start here.
The tl;dr is that PEP 668 provides a mechanism – a specially-named sentinel file at a particular location – to declare a Python installation/environment as “externally-managed” (its packages are installed and updated via some non-
pip
package manager, such asapt
). Recent versions ofpip
respect this and will refuse to install packages into such an “externally-managed” Python environment.Debian are marking their default system Python as “externally managed”, so any workflows on any Debian-based distros which assumed the ability to do a
pip install
with the system Python will be broken and will have to either switch to usingapt
to install the desired packages, or create and use a Python virtual environment topip install
into.Posting this today because Ubuntu 23.04 has been out for a few days and people are apparently tripping over this as they upgrade to it.
(I am and long have been on Team Use A Venv, Always, Yes, Even In A Container, Really” and recommend you join us)
From my experience, this was already broken in practice. The moment you did that on a Debian box the python situation was so messed up you could rather reinstall than try to fix it.
That’s a big part of why this feature was developed.
It’s going to be a problem mostly for Debian-based containers, where you treat the system Python as your environment (for good reason - you’ll never upgrade afterwards anyway).
That’s definitely going to break some stuff at work… but I’m happy to see it.
sudo pip install
causes no end of trouble already.I’m curious if this will also affect
pip install
into the user home. I’d love it if I could prevent that from working too.As specified in the PEP, the process for a compliant installer is that if it detects it’s not running in a venv and it finds the
EXTERNALLY-MANAGED
sentinel file at the correct location, it’s supposed to instantly bail out and display an error message (and the sentinel file can provide the error message to display).However, a user with sufficient system permissions can still work around this by passing an explicit
--break-system-packages
flag topip install
. So it’s not a full lockdown.I think I will keep quiet about the
--break-system-packages
escape-valve unless there’s an emergency. :-)I wonder if I could add an
EXTERNALLY-MANAGED
file to my home directory somewhere?The name of that flag is perfect.
It’s a weird state that system python’s have to be there (for the system) but are effectively always too broken to use (same on macOS and even with Homebrew).
Aw, had my hopes up.
When you do an April Fools joke and everyone’s reaction is ‘Hurray! Oh, it’s a joke, never mind’, that might be a clue that you’re going down the wrong path.
The “announcement” isn’t from Canonical themselves.
Check out that timeline. Microsoft fixed the vulnerability for Bing immediately… and then failed to proactively check for the same kind of mistake on any of their other applications. It was only when the researcher reported the results of their own scans 3+ weeks later that Microsoft took broader action.
This is an important lesson: If you made the mistake in one place, you probably made it elsewhere too. Look for other instances of the same problem.
Microsoft got extremely lucky, here. $40k is not too shabby, but learning this the hard way would have cost tens of millions.
This is astoundingly good advice for life in general, not just coding :)
Hah! I suppose so. :-)
If you’re asking this question, that means you haven’t understood the idea behind CORS. :-) As far as I am aware, nothing aside from a browser even gives the CORS headers a second glance. They don’t do anything in and of themselves; they are purely instructions to a browser to say “here’s how these sites can interact”.
“A way to relax the same-origin policy” is indeed correct. The thing to keep in mind though is that the SOP is purely a concept in browser-land. Nothing else cares about it.
SQL injection is solved - in theory - by escaping inputs properly or better by prepared queries. Of course it’s been a hugely disappointing disaster trying to get practice to keep up. Anyway..
There seems to be no way to correctly prevent prompt injection, is there? You can push the probability down by adding more guard rules to the prompts, but I don’t trust that.
Perhaps a multi-modal version needs to be trained, with a system prompt completely separate from the user input? I really don’t know if that would even help. Who knows?
I’d wager there’s no general way to prevent this sort of thing in a text autocompletion engine.
If it were transforming trees, or structured text, then quotation marks would not just suggest an inner block of text, but denote a hard barrier between outer and inner context.
At that point, the problem shifts to prompt engineering again, since the prompt must direct the transformer to use the quotation blocks when appropriate.
I don’t understand LLMs really, but ISTM they lex stuff into tokens, right? Couldn’t you make up a token that is deliberately excluded from the semantics of the universe and then use it as a barrier? Essentially, the fnord solution.
There are at least two special tokens present in the training process of these systems to mark the start and the end of the text. There is no way for a human to type these two tokens into the prompt, because no utf-8 sequence of characters would produce them.
Introducing a third special token (or however many) and using it as a separator could prove very effective at avoiding prompt injection. The main challenge here is that the network would have to be retrained (or at least fine-tuned) to understand the semantics of this new token, and training data adjusted to use it consistently.
Yes, it would need to be added in at the very beginning of the process. All of these prompt jailbreaks come by overcoming the late additions that are either fine tuned or worse just one shot learning.
I’ve had some decent results by block-quoting the user input in a prompt, but nothing definitive. I think the only safe solution here is to treat the LLM output as unsanitized user input, and not eval it in a trusted environment.
I’ve had limited success by parsing the model’s output. The model definitely appeared to fuzz the parser!
I think it’s interesting how comparatively few words humans need to encounter in childhood to reach the level of intelligence they develop. Either the brain is far more powerful than any computer system we have, our learning algorithms are far below the level of efficiency they could achieve, other human sensory stimuli fill in the gap, or the brain is not a computer. The last one seems hard to believe but as seems popular to point out, humans love believing the technology du jour (the wheel, books, mechanical systems, now computers) to be the true nature of reality. Brains could be an entirely new category of technology beyond computers we have yet to develop or conceive.
LLMs have, to a close approximation, read every word ever written by humans. That isn’t close to true of even the greatest geniuses our species has produced.
If you want to continue the rabbit hole of brains being an entirely new kind of technology, you may be interested in this post:
(As well: this response)
Biology constantly shows us how much further we have to go in the depth of our understanding.
My understanding is that the process of training a LLM on a (very) large collection of text is not at all like a person reading. The current LLMs are super impressive and surprising but they have taken a different path from human cognition.
There is a relatively big community of AI researchers who explore techniques to make learning a lot more efficient. This book provides a nice CS-oriented summary [1].
In a nutshell, humans are very good at building abstractions using hierarchies and mixtures of concepts. These map quite nicely to the eponymous models in statistics.
[1] https://probmods.org
I suspect our brains come with a certain amount of implicit knowledge built in and just need to connect it to words. (How else could you communicate the concept of “thoughts” to a child?) This wouldn’t explain everything, but it would give us a head start.
There’s some pretty famous research that was done in remote parts of (at the time) the USSR with people who were not and never had been literate, and which established some fascinating things about the changes in our thinking literacy – even slight literacy – produces. One of which is the concept of words as things, and as things that can be reasoned about, have things predicated of them, and so on. You almost certainly take that and many other similar abstract-concepts-as-things for granted, but you were not born with them.
(if you want to dig more into this, read up on Walter Ong – his work, or even just a good summary or any good bibliography will turn up more things to read on the subject)
Literacy is another topic entirely, although I’m sure it does have dramatic effects on the brain. I’m talking about how the developing brain connects the concept of heavy with the spoken word “heavy”, or the idea of being helpful with the word “help”. Parents chattering at children (describing their behavior to them) and children being little sponges is critical, but I suspect there’s also a pre-built set of templates that are waiting for words to match up to.
Visual sensory input is absurdly high bandwidth compared to text. It’s not surprising that it takes a large amount of text to reach comprehension. If anything, it’s amazing how little input is needed. I suspect this is because text input is relatively high entropy (i.e. information density) compared to vision.
GPT4 is trained on both text and images, and shows considerably improved comprehension. Most likely, adding video and audio input would have a similar affect, although the computational demands would be much, much higher.
Any thoughts along these lines will have to contend with the existence of Hellen Keller, though.
Fair point. Touch, too, is much higher bandwidth than text. But also much lower information density. Smell and taste are less clear.
Edit: but also agree with others that there is some built-in bias (via evolution) on what humans can efficiently learn. Just as there is some built-in bias of what any given artificial neural network architecture can efficiently learn.
This seems like a good pattern with an utterly terrible name. I’m never going to use or remember that name, because it doesn’t make sense to me even now, having just read an explanation of it!
Even just “agile cutover” (to make up a term) would be a better name.
So… which operating systems protect against this by default? I’m hoping at least some do…
The Linux kernel commit linked on the post mentions at least this:
Between the dually analogized name
Steel Threads
and the following description:followed by Step 1 from the example:
I’m left wondering what I’m doing in step 1? Am I defining a thinnest possible version of something that crosses some boundaries of a system that constitutes one important use case? What does that mean?
I am left with so many more questions.
I’m not pooh-poohing on the concept. I’ve used the development pattern that I think Steel Threads attempts to describe, and I don’t think the name Steel Threads is useful or descriptive. What I’m hearing described is more of a development pattern mixed with a release strategy, and “steel threads” makes it sound like a specific tool or implementation detail. I understand why Wikipedia removed the article.
I have literally done all of the various approaches the author mentions, and I am still left confused about what Steel Threads actually means.
I think this is a poorly-defined pattern that is better expressed in other ways.
It strikes me as tech garbage language.
That was a good read, thanks. Intensely triggering, but good.
Oh my god this is amazing.
The poem about ECB is worth the price of admission alone. Solid article @soatok.
When you said a poem about ECB I wondered if it was going to be something like:
Looks like this is basically a syntactic version of
zip
. (Presumably with some performance improvement overzip
due to not having to build tuples.)From the name I was expecting it might be like Clojure’s
for
macro, which is more like nested loops (but with filtering and binding).Boy, there sure are a lot of people who haven’t read the proposal but want to write opinions about it.
It’s indeed sad that this thread is dominated by hot-take reactions to the word “telemetry” mostly bringing up points already addressed by two long, thoughtful, evenhanded TFAs. I expected better, lobsters.
read the proposal, and still don’t want google to open this can of worms. what’s your point?
specifically, I don’t like how google will now include machinery to automatically phone home. I don’t have a problem with the current plans, especially that it’s now opt-in, but I have a problem with the idea that it will be very very hard for future google to ignore that they can now siphon data from anyone running Go apps. today it’s “anonymous, random” stuff, tomorrow it’s…. ?
My point is just that there are a lot of people who clearly haven’t read the proposal and who are invoking things like “but GDPR!” and “oh no, they’ll be able to build usage patterns”. (Not just here in this discussion page.) They clearly haven’t looked at the proposed mechanisms and the great care they would take to keep identifiable and invasive information out of the reports. It’s not perfect—there are changes I would make—but it’s better than many of the accusations being leveled against it.
Some people are instead just objecting on the basis of “Google is trying to slurp up information”. (In fact, while Golang came from Google and is still moderately associated with it, this isn’t Google per se, although I understand that that perception is real.) And that might be an OK objection if they used correct information, but most aren’t. I think if you want to object on that basis, you have to make a reasonable comparison with the current state of things. The Go team could try to do a frog-boil and start with innocuous telemetry and later start sneaking in some more invasive stuff, but… let’s be honest, we’ve got a community of detail-oriented nerds with strong opinions here. I don’t think it would work! And maybe they’d push it through anyway, but they could already do that today.
Honestly, it’s just very unfortunate that Go is the project bringing this proposal forward. I think that if a Python linter proposed this, the discussion would be going very differently. (And then depending on how that turned out, the Go folks could decide to adopt the same thing.) Someone has to pioneer privacy-preserving telemetry so that we can then go to existing projects and say “hey, use this instead”. Anything Google-associated is kind of doomed, though.
What do you mean by “anyone running Go apps”? Are you implying that the telemetry would be inserted into programs compiled by the Go compiler?
They did not read the proposal.
¿Por qué no los dos? The best names are unique and memorable but also have some relation to the functionality.