Recent changes to this wiki:

fix: link
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index 46d5473..2634ed3 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -5,7 +5,7 @@
 [Daniel]: https://blog.digital-scurf.org/
 [Mark]: https://blog.sirena.org.uk/
 [Vince]: http://vincentsanders.blogspot.com/
-[test Firefox more efficiently]: https://blog.liw.fi/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla/
+[test Firefox more efficiently]: https://hacks.mozilla.org/2020/07/testing-firefox-more-efficiently-with-machine-learning/
 
 For our book club this time, [Daniel][], [Mark][] and I were joined by
 [Vince][] to discuss an article about using machine-learning to [test

publish
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index 995ae48..46d5473 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Book club: Testing Firefox more efficiently with machine learning by Mozilla"]]
-[[!tag draft firefox mozilla testing machine-learning book-club]]
+[[!tag firefox mozilla testing machine-learning book-club]]
 [[!meta date="2020-08-04 08:47"]]
 
 [Daniel]: https://blog.digital-scurf.org/

fix: clarify sentence and argument
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index 7186951..995ae48 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -54,8 +54,8 @@ to meet various conflicting needs and requirements.
 
 Large code bases are different from small ones. The sheer scale of
 things brings problems rarely seen in smaller code bases, and expose
-problems in compilers, operating systems, and even hardware, which
-small projects rarely do. Large projects tend to also have more flaky
+more problems in compilers, operating systems, and even hardware, than
+most small projects do. Large projects tend to also have more flaky
 tests (tests that sometimes fail for no obvious reason, but sometimes
 pass). Large projects may also have to make different kinds of careful
 compromises when tests fail, to maintain forward momentum.

fix: clarify sentence
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index 991ca6b..7186951 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -27,8 +27,8 @@ every configuration for every push takes time and causes friction in
 the development process: other developers have to wait for your push
 to finish testing.
 
-The goal of the work reported on in this blog post is about
-reducing the number of tests without sacrificing quality, using
+The goal of the work reported on in this blog post is about reducing
+the number of tests that are run without sacrificing quality, using
 machine-learning technologies. Previously, Mozilla has prioritised
 some configurations over others, and runs a smaller set of tests for
 some than others, or runs tests less frequently. They also integrate

fix: use simpler word
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index 974c58e..991ca6b 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -27,7 +27,7 @@ every configuration for every push takes time and causes friction in
 the development process: other developers have to wait for your push
 to finish testing.
 
-The goal of the experimentation reported on in this blog post is about
+The goal of the work reported on in this blog post is about
 reducing the number of tests without sacrificing quality, using
 machine-learning technologies. Previously, Mozilla has prioritised
 some configurations over others, and runs a smaller set of tests for

fix: add article authors
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index a8316fa..974c58e 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -9,10 +9,11 @@
 
 For our book club this time, [Daniel][], [Mark][] and I were joined by
 [Vince][] to discuss an article about using machine-learning to [test
-Firefox more efficiently][]. A short summary follows. I should note
-that part of the article dives into maths, which is beyond my
-understanding, but we tried to understand what Mozilla is trying to
-achieve, even if we skimped on understanding the details of how.
+Firefox more efficiently][] by Andrew Halberstadt and Marco
+Castelluccio. A short summary follows. I should note that part of the
+article dives into maths, which is beyond my understanding, but we
+tried to understand what Mozilla is trying to achieve, even if we
+skimped on understanding the details of how.
 
 Mozilla has roughly 85 thousand tests for Firefox, which is built for
 about 90 configurations (combinations of target operating system,

fix: wording
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index fa29fbc..a8316fa 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -7,7 +7,7 @@
 [Vince]: http://vincentsanders.blogspot.com/
 [test Firefox more efficiently]: https://blog.liw.fi/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla/
 
-For the book club this time, [Daniel][], [Mark][] and I were joined by
+For our book club this time, [Daniel][], [Mark][] and I were joined by
 [Vince][] to discuss an article about using machine-learning to [test
 Firefox more efficiently][]. A short summary follows. I should note
 that part of the article dives into maths, which is beyond my

fix: no citeproc
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
index 60e786e..fa29fbc 100644
--- a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -5,12 +5,13 @@
 [Daniel]: https://blog.digital-scurf.org/
 [Mark]: https://blog.sirena.org.uk/
 [Vince]: http://vincentsanders.blogspot.com/
+[test Firefox more efficiently]: https://blog.liw.fi/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla/
 
 For the book club this time, [Daniel][], [Mark][] and I were joined by
-[Vince][] to discuss an article about using machine-learning to test
-Firefox more efficiently (@halcas2020]). A short summary follows. I
-should note that part of the article dives into maths, which is beyond
-my understanding, but we tried to understand what Mozilla is trying to
+[Vince][] to discuss an article about using machine-learning to [test
+Firefox more efficiently][]. A short summary follows. I should note
+that part of the article dives into maths, which is beyond my
+understanding, but we tried to understand what Mozilla is trying to
 achieve, even if we skimped on understanding the details of how.
 
 Mozilla has roughly 85 thousand tests for Firefox, which is built for
@@ -74,14 +75,3 @@ code module fail unusually often?
 
 Overall, we liked the article. It reports on work in progress, and we
 look forward to learning more.
-
----
-references:
-- id: halcas2020
-  issued:
-    date-parts:
-	- [2020, 7, 9]
-  type: post
-  title: "Testing Firefox more efficiently with machine learning"
-  URL: https://hacks.mozilla.org/2020/07/testing-firefox-more-efficiently-with-machine-learning/
-...

creating tag page tag/firefox
diff --git a/tag/firefox.mdwn b/tag/firefox.mdwn
new file mode 100644
index 0000000..617785c
--- /dev/null
+++ b/tag/firefox.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged firefox"]]
+
+[[!inline pages="tagged(firefox)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/machine-learning
diff --git a/tag/machine-learning.mdwn b/tag/machine-learning.mdwn
new file mode 100644
index 0000000..6ae664b
--- /dev/null
+++ b/tag/machine-learning.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged machine-learning"]]
+
+[[!inline pages="tagged(machine-learning)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/mozilla
diff --git a/tag/mozilla.mdwn b/tag/mozilla.mdwn
new file mode 100644
index 0000000..cb6e453
--- /dev/null
+++ b/tag/mozilla.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged mozilla"]]
+
+[[!inline pages="tagged(mozilla)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
new file mode 100644
index 0000000..60e786e
--- /dev/null
+++ b/posts/2020/08/04/book_club_testing_firefox_more_efficiently_with_machine_learning_by_mozilla.mdwn
@@ -0,0 +1,87 @@
+[[!meta title="Book club: Testing Firefox more efficiently with machine learning by Mozilla"]]
+[[!tag draft firefox mozilla testing machine-learning book-club]]
+[[!meta date="2020-08-04 08:47"]]
+
+[Daniel]: https://blog.digital-scurf.org/
+[Mark]: https://blog.sirena.org.uk/
+[Vince]: http://vincentsanders.blogspot.com/
+
+For the book club this time, [Daniel][], [Mark][] and I were joined by
+[Vince][] to discuss an article about using machine-learning to test
+Firefox more efficiently (@halcas2020]). A short summary follows. I
+should note that part of the article dives into maths, which is beyond
+my understanding, but we tried to understand what Mozilla is trying to
+achieve, even if we skimped on understanding the details of how.
+
+Mozilla has roughly 85 thousand tests for Firefox, which is built for
+about 90 configurations (combinations of target operating system,
+build flags, and so on), and they get around 300 pushes to version
+control per day. That's about 2.3 billion individual tests to run
+every day.
+
+Running that many tests takes a lot of hardware resources, and so it
+has a real cost. Beyond the financial aspect, running all tests for
+every configuration for every push takes time and causes friction in
+the development process: other developers have to wait for your push
+to finish testing.
+
+The goal of the experimentation reported on in this blog post is about
+reducing the number of tests without sacrificing quality, using
+machine-learning technologies. Previously, Mozilla has prioritised
+some configurations over others, and runs a smaller set of tests for
+some than others, or runs tests less frequently. They also integrate
+into a dedicated integration branch, and merge from that into the main
+branch manually, using dedicated people, "code sheriffs", who make
+informed decisions.
+
+The machine-learning approach is based on the realisation that one can
+deduce patterns from historical data: if this module changes, then if
+any tests fail it's probably this set of tests. Thus, when a new
+change comes in, analysing what has changed can inform what tests to
+run, or in which order to run them. For CI, if the automated tests
+will fail, it's better that they fail fast. Not only does this mean
+developers get feedback sooner, and can start fixing things earlier,
+but also the other tests don't necessarily need to be run at all.
+
+The book club group had long discussion about the article. Overall we
+found Mozilla's approach to testing the Firefox browser impressive. We
+certainly understand the motivation to reduce number of tests run
+without compromising on quality. It seems to be an issue that many
+large software projects have to face: it's one more thing to balance
+to meet various conflicting needs and requirements.
+
+Large code bases are different from small ones. The sheer scale of
+things brings problems rarely seen in smaller code bases, and expose
+problems in compilers, operating systems, and even hardware, which
+small projects rarely do. Large projects tend to also have more flaky
+tests (tests that sometimes fail for no obvious reason, but sometimes
+pass). Large projects may also have to make different kinds of careful
+compromises when tests fail, to maintain forward momentum.
+
+We each had some amusing stories about how machine-learning can fail
+amusingly, but it seems Mozilla is doing things in ways that should
+avoid most of the inexplicable failures. We had some thoughts about
+how Mozilla might use their historical data and machine-learning more.
+For example, perhaps ML could identify flaky tests automatically:
+tests that fail unusually much, even when nothing seemingly related to
+the them has changed? Or perhaps identifying tests that become flaky?
+
+Maybe ML could identify parts of code that could do with quality
+improvement: specific code modules that result in test failures
+unusually often? Or identify hidden, undeclared coupling between parts
+of the code: if this code module is changed, then tests for this other
+code module fail unusually often?
+
+Overall, we liked the article. It reports on work in progress, and we
+look forward to learning more.
+
+---
+references:
+- id: halcas2020
+  issued:
+    date-parts:
+	- [2020, 7, 9]
+  type: post
+  title: "Testing Firefox more efficiently with machine learning"
+  URL: https://hacks.mozilla.org/2020/07/testing-firefox-more-efficiently-with-machine-learning/
+...

fix: link
diff --git a/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn b/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn
index 5f25a66..36bbc8d 100644
--- a/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn
+++ b/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn
@@ -6,7 +6,7 @@ I [asked a couple of weeks
 ago](https://toot.liw.fi/@liw/103729502946243759) what people like or
 hate about email. Here's a summary of the responses. I admit the
 summary may be tainted by my current thinking about [re-inventing
-email](https://ideas.liw.fi/email2.html).
+email](https://ideas.liw.fi/rethinking-email.html).
 
 # Like
 

publish
diff --git a/posts/2020/05/21/transfer_speeds.mdwn b/posts/2020/05/21/transfer_speeds.mdwn
index 16b7d37..002efa6 100644
--- a/posts/2020/05/21/transfer_speeds.mdwn
+++ b/posts/2020/05/21/transfer_speeds.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Transfer speeds"]]
 [[!meta date="2020-05-21 13:44"]]
-[[!tag draft fling network bandwidth]]
+[[!tag fling network bandwidth]]
 
 I was curious about how fast I can transfer data in various contexts.
 I did some informal benchmarks: these are not scientific, and your

tweaks
diff --git a/posts/2020/05/21/transfer_speeds.mdwn b/posts/2020/05/21/transfer_speeds.mdwn
index 943466f..16b7d37 100644
--- a/posts/2020/05/21/transfer_speeds.mdwn
+++ b/posts/2020/05/21/transfer_speeds.mdwn
@@ -2,14 +2,14 @@
 [[!meta date="2020-05-21 13:44"]]
 [[!tag draft fling network bandwidth]]
 
-I was curious about how fast data can be transferred in various
-contexts. I did some informal benhcmarking: your results might be
-different.
+I was curious about how fast I can transfer data in various contexts.
+I did some informal benchmarks: these are not scientific, and your
+results might be different.
 
 The data transferred is a one terabyte sparse file:
 
 ~~~sh
-truncate --size 1T terabyte
+$ truncate --size 1T terabyte
 ~~~
 
 First is just copying files on a disk: from the file to /dev/null.
@@ -25,7 +25,8 @@ dd bs=1G            |exolobe1            |exolobe1            |328
 
 Conclusion: cat is quite good, and setting almost any size buffer on
 dd is a win over the default. (dd has other options that cat lacks,
-such as oflag=direct, which means its still useful for me.)
+such as oflag=direct, which means its still interesting for me,
+despite a little slower than cat.)
 
 Then network transfers. I use the
 [fling](https://github.com/rjek/fling) software, which is quite
@@ -38,8 +39,8 @@ under qemu-system on the same laptop, or my server (exolobe2), or a VM
 on the server (holywood2).
 
 ~~~sh
-on sender: fling -p terabyte receiver 8888
-on receiver: fling -r 8888 > /dev/null
+$ fling -p terabyte receiver 8888     # sender
+$ receiver: fling -r 8888 > /dev/null # receiver
 ~~~
 
 For extra kicks, transfers between nested VMs inside a VM on the

table tweaks
diff --git a/posts/2020/05/21/transfer_speeds.mdwn b/posts/2020/05/21/transfer_speeds.mdwn
index d6e17ba..943466f 100644
--- a/posts/2020/05/21/transfer_speeds.mdwn
+++ b/posts/2020/05/21/transfer_speeds.mdwn
@@ -15,12 +15,12 @@ truncate --size 1T terabyte
 First is just copying files on a disk: from the file to /dev/null.
 
 [[!table data="""
-software            |sender              |receiver            |time (s)            |speed (MB/s)        |
-cat                 |exolobe1            |exolobe1            |274                 |3826                |
-dd                  |exolobe1            |exolobe1            |2729                |384                 |
-dd bs=1M            |exolobe1            |exolobe1            |304                 |3449                |
-dd bs=16M           |exolobe1            |exolobe1            |314                 |3338                |
-dd bs=1G            |exolobe1            |exolobe1            |328                 |3196                |
+software            |sender              |receiver            |time (s)            |speed (MB/s)
+cat                 |exolobe1            |exolobe1            |274                 |3826
+dd                  |exolobe1            |exolobe1            |2729                |384
+dd bs=1M            |exolobe1            |exolobe1            |304                 |3449
+dd bs=16M           |exolobe1            |exolobe1            |314                 |3338
+dd bs=1G            |exolobe1            |exolobe1            |328                 |3196
 """]]
 
 Conclusion: cat is quite good, and setting almost any size buffer on
@@ -46,23 +46,16 @@ For extra kicks, transfers between nested VMs inside a VM on the
 laptop, where the outer VM is running under libvirt or qemu-system.
 The nested VMs always run under libvirt.
 
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|software            |sender              |receiver            |time (s)            |speed (MB/s)        |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |exolobe1            |exolobe1            |395                 |2655                |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |exolobe1            |libvirt guest       |613                 |1710                |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |exolobe1            |qemu-system-x86_64  |4653                |225                 |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |exolobe1            |exolobe2            |too long            |111                 |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |exolobe1            |holywood2           |too long            |78                  |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |nested libvirt-guest|other nested guest  |too long            |280                 |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|fling               |nested qemu-system  |other such          |too long            |12                  |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
+[[!table data="""
+software            |sender              |receiver            |time (s)            |speed (MB/s)
+fling               |exolobe1            |exolobe1            |395                 |2655
+fling               |exolobe1            |libvirt guest       |613                 |1710
+fling               |exolobe1            |qemu-system-x86_64  |4653                |225
+fling               |exolobe1            |exolobe2            |too long            |111
+fling               |exolobe1            |holywood2           |too long            |78
+fling               |nested libvirt-guest|other nested guest  |too long            |280
+fling               |nested qemu-system  |other such          |too long            |12
+"""]]
 
 The "too long" results is because I got impatient. The speeds in those
 cases are from fling -p output.

table tweak
diff --git a/posts/2020/05/21/transfer_speeds.mdwn b/posts/2020/05/21/transfer_speeds.mdwn
index a3b48d2..d6e17ba 100644
--- a/posts/2020/05/21/transfer_speeds.mdwn
+++ b/posts/2020/05/21/transfer_speeds.mdwn
@@ -14,19 +14,14 @@ truncate --size 1T terabyte
 
 First is just copying files on a disk: from the file to /dev/null.
 
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|software            |sender              |receiver            |time (s)            |speed (MB/s)        |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|cat                 |exolobe1            |exolobe1            |274                 |3826                |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|dd                  |exolobe1            |exolobe1            |2729                |384                 |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|dd bs=1M            |exolobe1            |exolobe1            |304                 |3449                |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|dd bs=16M           |exolobe1            |exolobe1            |314                 |3338                |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
-|dd bs=1G            |exolobe1            |exolobe1            |328                 |3196                |
-+--------------------+--------------------+--------------------+--------------------+--------------------+
+[[!table data="""
+software            |sender              |receiver            |time (s)            |speed (MB/s)        |
+cat                 |exolobe1            |exolobe1            |274                 |3826                |
+dd                  |exolobe1            |exolobe1            |2729                |384                 |
+dd bs=1M            |exolobe1            |exolobe1            |304                 |3449                |
+dd bs=16M           |exolobe1            |exolobe1            |314                 |3338                |
+dd bs=1G            |exolobe1            |exolobe1            |328                 |3196                |
+"""]]
 
 Conclusion: cat is quite good, and setting almost any size buffer on
 dd is a win over the default. (dd has other options that cat lacks,

creating tag page tag/fling
diff --git a/tag/fling.mdwn b/tag/fling.mdwn
new file mode 100644
index 0000000..3fe8d62
--- /dev/null
+++ b/tag/fling.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged fling"]]
+
+[[!inline pages="tagged(fling)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/network
diff --git a/tag/network.mdwn b/tag/network.mdwn
new file mode 100644
index 0000000..245409e
--- /dev/null
+++ b/tag/network.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged network"]]
+
+[[!inline pages="tagged(network)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/bandwidth
diff --git a/tag/bandwidth.mdwn b/tag/bandwidth.mdwn
new file mode 100644
index 0000000..3c80b41
--- /dev/null
+++ b/tag/bandwidth.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged bandwidth"]]
+
+[[!inline pages="tagged(bandwidth)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/05/21/transfer_speeds.mdwn b/posts/2020/05/21/transfer_speeds.mdwn
new file mode 100644
index 0000000..a3b48d2
--- /dev/null
+++ b/posts/2020/05/21/transfer_speeds.mdwn
@@ -0,0 +1,78 @@
+[[!meta title="Transfer speeds"]]
+[[!meta date="2020-05-21 13:44"]]
+[[!tag draft fling network bandwidth]]
+
+I was curious about how fast data can be transferred in various
+contexts. I did some informal benhcmarking: your results might be
+different.
+
+The data transferred is a one terabyte sparse file:
+
+~~~sh
+truncate --size 1T terabyte
+~~~
+
+First is just copying files on a disk: from the file to /dev/null.
+
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|software            |sender              |receiver            |time (s)            |speed (MB/s)        |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|cat                 |exolobe1            |exolobe1            |274                 |3826                |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|dd                  |exolobe1            |exolobe1            |2729                |384                 |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|dd bs=1M            |exolobe1            |exolobe1            |304                 |3449                |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|dd bs=16M           |exolobe1            |exolobe1            |314                 |3338                |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|dd bs=1G            |exolobe1            |exolobe1            |328                 |3196                |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+
+Conclusion: cat is quite good, and setting almost any size buffer on
+dd is a win over the default. (dd has other options that cat lacks,
+such as oflag=direct, which means its still useful for me.)
+
+Then network transfers. I use the
+[fling](https://github.com/rjek/fling) software, which is quite
+efficient when security is not needed. It does not handle sparse files
+specially.
+
+Source of the transfer is my laptop (exolobe1), target is the same
+machine over localhost, a VM under libvirt on the same laptop, a VM
+under qemu-system on the same laptop, or my server (exolobe2), or a VM
+on the server (holywood2).
+
+~~~sh
+on sender: fling -p terabyte receiver 8888
+on receiver: fling -r 8888 > /dev/null
+~~~
+
+For extra kicks, transfers between nested VMs inside a VM on the
+laptop, where the outer VM is running under libvirt or qemu-system.
+The nested VMs always run under libvirt.
+
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|software            |sender              |receiver            |time (s)            |speed (MB/s)        |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |exolobe1            |exolobe1            |395                 |2655                |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |exolobe1            |libvirt guest       |613                 |1710                |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |exolobe1            |qemu-system-x86_64  |4653                |225                 |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |exolobe1            |exolobe2            |too long            |111                 |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |exolobe1            |holywood2           |too long            |78                  |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |nested libvirt-guest|other nested guest  |too long            |280                 |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+|fling               |nested qemu-system  |other such          |too long            |12                  |
++--------------------+--------------------+--------------------+--------------------+--------------------+
+
+The "too long" results is because I got impatient. The speeds in those
+cases are from fling -p output.
+
+Conclusion: localhost is fast. libvirt networking inside the same
+physical machine is fast. Every other case is slow.
+
+I hope that's useful to someone.

fix: markup typos
diff --git a/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn b/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn
index 57defaf..743d7e1 100644
--- a/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn
+++ b/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn
@@ -3,5 +3,5 @@
 [[!tag book-club git]]
 
 We had our third book club meeting yesterday. Daniel posted his
-}summary of our
+[summary of our
 discussion](https://blog.digital-scurf.org/posts/bookclub-20200511/).

Publish log entry
diff --git a/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn b/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn
new file mode 100644
index 0000000..57defaf
--- /dev/null
+++ b/posts/2020/05/12/book_club_the_communicative_value_of_using_git_well.mdwn
@@ -0,0 +1,7 @@
+[[!meta title="Book club: The communicative value of using Git well"]]
+[[!meta date="2020-05-12 10:02"]]
+[[!tag book-club git]]
+
+We had our third book club meeting yesterday. Daniel posted his
+}summary of our
+discussion](https://blog.digital-scurf.org/posts/bookclub-20200511/).

Publish log entry
diff --git a/posts/2020/05/07/i_miss_inboxes.mdwn b/posts/2020/05/07/i_miss_inboxes.mdwn
new file mode 100644
index 0000000..58d4fda
--- /dev/null
+++ b/posts/2020/05/07/i_miss_inboxes.mdwn
@@ -0,0 +1,28 @@
+[[!meta title="I miss inboxes"]]
+[[!tag rant]]
+[[!meta date="2020-05-07 11:05"]]
+
+I don't like the "infinite scroll" or "never-ending stream" type of
+communication application. I prefer to have a clear "inbox", where
+messages go, and from where I can remove them when I'm done with them.
+The reason I like inboxes is that they make it easier to keep track of
+things and harder to miss or forget about things. With the stream, I
+have to capture the message into my GTD system or I'll miss it.
+Obviously I can do that, and I do, but it's less convenient.
+
+(Note that for the purposes of this rant, whether all your incoming
+messages go into one inbox or are automatically filtered into many is
+irrelevant.)
+
+Another reason is that in the streaming model it's harder to look at
+only the messages that have arrived since I last looked, say overnight
+while I slept, or while I was busy doing other things. This makes it
+even easier to accidentally miss important things.
+
+Examples of inboxes: email, SMS.
+
+Examples of streams: Twitter, Mastodon, IRC, Matrix, Telegram, RSS
+feeds.
+
+You may notice that all "modern" applications tend to be streams. In
+this, too, I feel like an old man shouting at clouds.
diff --git a/posts/2020/05/07/i_miss_inboxes/hosted-ick.svg b/posts/2020/05/07/i_miss_inboxes/hosted-ick.svg
new file mode 100644
index 0000000..36d39bb
--- /dev/null
+++ b/posts/2020/05/07/i_miss_inboxes/hosted-ick.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.40.1 (20161225.0304)
+ -->
+<!-- Title: project Pages: 1 -->
+<svg width="1238pt" height="659pt"
+ viewBox="0.00 0.00 1237.97 658.99" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 654.992)">
+<title>project</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-654.992 1233.9691,-654.992 1233.9691,4 -4,4"/>
+<!-- hosted_ick -->
+<g id="node1" class="node">
+<title>hosted_ick</title>
+<polygon fill="#f4bada" stroke="#000000" points="739.8026,-106 623.8026,-53 739.8026,0 855.8026,-53 739.8026,-106"/>
+<text text-anchor="middle" x="739.8026" y="-64.3" font-family="Times,serif" font-size="14.00" fill="#000000">Lars runs a hosted</text>
+<text text-anchor="middle" x="739.8026" y="-49.3" font-family="Times,serif" font-size="14.00" fill="#000000">Ick service for</text>
+<text text-anchor="middle" x="739.8026" y="-34.3" font-family="Times,serif" font-size="14.00" fill="#000000">himself and users</text>
+</g>
+<!-- user_friendly -->
+<g id="node2" class="node">
+<title>user_friendly</title>
+<polygon fill="#f4bada" stroke="#000000" points="213.3026,-237.7965 104.3026,-237.7965 104.3026,-184.7965 213.3026,-184.7965 213.3026,-237.7965"/>
+<text text-anchor="middle" x="158.8026" y="-222.5965" font-family="Times,serif" font-size="14.00" fill="#000000">Ick is reasonably</text>
+<text text-anchor="middle" x="158.8026" y="-207.5965" font-family="Times,serif" font-size="14.00" fill="#000000">user friendly to</text>
+<text text-anchor="middle" x="158.8026" y="-192.5965" font-family="Times,serif" font-size="14.00" fill="#000000">techies.</text>
+</g>
+<!-- user_friendly&#45;&gt;hosted_ick -->
+<g id="edge1" class="edge">
+<title>user_friendly&#45;&gt;hosted_ick</title>
+<path fill="none" stroke="#000000" d="M213.5,-194.874C261.6555,-180.5345 333.7345,-159.3597 396.8026,-142 484.4307,-117.88 585.1499,-91.959 654.668,-74.3484"/>
+<polygon fill="#000000" stroke="#000000" points="655.8572,-77.6579 664.6931,-71.8116 654.14,-70.8718 655.8572,-77.6579"/>
+</g>
+<!-- secure_from_users -->
+<g id="node3" class="node">
+<title>secure_from_users</title>
+<polygon fill="#f4bada" stroke="#000000" points="521.3026,-237.7965 406.3026,-237.7965 406.3026,-184.7965 521.3026,-184.7965 521.3026,-237.7965"/>
+<text text-anchor="middle" x="463.8026" y="-222.5965" font-family="Times,serif" font-size="14.00" fill="#000000">Ick is safe and</text>
+<text text-anchor="middle" x="463.8026" y="-207.5965" font-family="Times,serif" font-size="14.00" fill="#000000">secure from users</text>
+<text text-anchor="middle" x="463.8026" y="-192.5965" font-family="Times,serif" font-size="14.00" fill="#000000">doing silly things.</text>
+</g>
+<!-- secure_from_users&#45;&gt;hosted_ick -->
+<g id="edge2" class="edge">
+<title>secure_from_users&#45;&gt;hosted_ick</title>
+<path fill="none" stroke="#000000" d="M510.3101,-184.6226C556.6868,-158.0239 628.154,-117.0347 679.0033,-87.8707"/>
+<polygon fill="#000000" stroke="#000000" points="680.9964,-90.7624 687.9296,-82.7511 677.5137,-84.6903 680.9964,-90.7624"/>
+</g>
+<!-- secure_for_users -->
+<g id="node4" class="node">
+<title>secure_for_users</title>
+<polygon fill="#f4bada" stroke="#000000" points="725.8026,-230.2965 621.8026,-230.2965 621.8026,-192.2965 725.8026,-192.2965 725.8026,-230.2965"/>
+<text text-anchor="middle" x="673.8026" y="-215.0965" font-family="Times,serif" font-size="14.00" fill="#000000">Ick is secure for</text>
+<text text-anchor="middle" x="673.8026" y="-200.0965" font-family="Times,serif" font-size="14.00" fill="#000000">users to use.</text>
+</g>
+<!-- secure_for_users&#45;&gt;hosted_ick -->
+<g id="edge3" class="edge">
+<title>secure_for_users&#45;&gt;hosted_ick</title>
+<path fill="none" stroke="#000000" d="M681.7637,-192.2022C690.5189,-171.2036 704.9783,-136.5237 717.2739,-107.0333"/>
+<polygon fill="#000000" stroke="#000000" points="720.5621,-108.2416 721.18,-97.6648 714.1012,-105.5478 720.5621,-108.2416"/>
+</g>
+<!-- on_demand_workers -->
+<g id="node5" class="node">
+<title>on_demand_workers</title>
+<polygon fill="#f4bada" stroke="#000000" points="869.3026,-237.7965 744.3026,-237.7965 744.3026,-184.7965 869.3026,-184.7965 869.3026,-237.7965"/>
+<text text-anchor="middle" x="806.8026" y="-222.5965" font-family="Times,serif" font-size="14.00" fill="#000000">Ick can create</text>
+<text text-anchor="middle" x="806.8026" y="-207.5965" font-family="Times,serif" font-size="14.00" fill="#000000">and destroy</text>
+<text text-anchor="middle" x="806.8026" y="-192.5965" font-family="Times,serif" font-size="14.00" fill="#000000">workers on demand</text>
+</g>
+<!-- on_demand_workers&#45;&gt;hosted_ick -->
+<g id="edge4" class="edge">
+<title>on_demand_workers&#45;&gt;hosted_ick</title>
+<path fill="none" stroke="#000000" d="M795.4369,-184.4436C786.4923,-163.3108 773.7371,-133.175 762.696,-107.0888"/>
+<polygon fill="#000000" stroke="#000000" points="765.837,-105.5303 758.716,-97.6854 759.3906,-108.2588 765.837,-105.5303"/>
+</g>
+<!-- trigger_service -->
+<g id="node6" class="node">
+<title>trigger_service</title>
+<ellipse fill="#ffffff" stroke="#000000" cx="1133.8026" cy="-211.2965" rx="96.3333" ry="69.0935"/>
+<text text-anchor="middle" x="1133.8026" y="-245.0965" font-family="Times,serif" font-size="14.00" fill="#000000">Ick can trigger</text>
+<text text-anchor="middle" x="1133.8026" y="-230.0965" font-family="Times,serif" font-size="14.00" fill="#000000">multiple builds when</text>
+<text text-anchor="middle" x="1133.8026" y="-215.0965" font-family="Times,serif" font-size="14.00" fill="#000000">a git repo changes,</text>
+<text text-anchor="middle" x="1133.8026" y="-200.0965" font-family="Times,serif" font-size="14.00" fill="#000000">or when an ick build</text>
+<text text-anchor="middle" x="1133.8026" y="-185.0965" font-family="Times,serif" font-size="14.00" fill="#000000">finishes, or after</text>
+<text text-anchor="middle" x="1133.8026" y="-170.0965" font-family="Times,serif" font-size="14.00" fill="#000000">some time has passed</text>
+</g>
+<!-- trigger_service&#45;&gt;hosted_ick -->
+<g id="edge5" class="edge">
+<title>trigger_service&#45;&gt;hosted_ick</title>
+<path fill="none" stroke="#000000" d="M1065.6802,-162.3622C1053.7224,-154.9396 1041.147,-147.8273 1028.8026,-142 963.9527,-111.3871 886.0267,-88.1039 827.4426,-73.0443"/>
+<polygon fill="#000000" stroke="#000000" points="828.0294,-69.5823 817.4756,-70.5134 826.3065,-76.367 828.0294,-69.5823"/>
+</g>
+<!-- multiarch -->
+<g id="node7" class="node">
+<title>multiarch</title>
+<polygon fill="#f4bada" stroke="#000000" points="1019.8026,-237.7965 887.8026,-237.7965 887.8026,-184.7965 1019.8026,-184.7965 1019.8026,-237.7965"/>
+<text text-anchor="middle" x="953.8026" y="-222.5965" font-family="Times,serif" font-size="14.00" fill="#000000">Ick supports building</text>
+<text text-anchor="middle" x="953.8026" y="-207.5965" font-family="Times,serif" font-size="14.00" fill="#000000">for multiple</text>
+<text text-anchor="middle" x="953.8026" y="-192.5965" font-family="Times,serif" font-size="14.00" fill="#000000">architectures.</text>
+</g>
+<!-- multiarch&#45;&gt;hosted_ick -->
+<g id="edge6" class="edge">
+<title>multiarch&#45;&gt;hosted_ick</title>
+<path fill="none" stroke="#000000" d="M926.6204,-184.4705C912.5419,-171.1134 894.7815,-155.0702 877.8026,-142 853.0478,-122.944 824.2005,-103.8948 799.2999,-88.338"/>
+<polygon fill="#000000" stroke="#000000" points="801.0132,-85.2822 790.67,-82.9868 797.3243,-91.2313 801.0132,-85.2822"/>
+</g>
+<!-- webui -->
+<g id="node8" class="node">
+<title>webui</title>
+<ellipse fill="#ffffff" stroke="#000000" cx="89.8026" cy="-581.6955" rx="89.6056" ry="58.8803"/>
+<text text-anchor="middle" x="89.8026" y="-607.9955" font-family="Times,serif" font-size="14.00" fill="#000000">Ick has a web UI</text>
+<text text-anchor="middle" x="89.8026" y="-592.9955" font-family="Times,serif" font-size="14.00" fill="#000000">that allows creation,</text>
+<text text-anchor="middle" x="89.8026" y="-577.9955" font-family="Times,serif" font-size="14.00" fill="#000000">updating, triggering</text>
+<text text-anchor="middle" x="89.8026" y="-562.9955" font-family="Times,serif" font-size="14.00" fill="#000000">of projects, builds,</text>
+<text text-anchor="middle" x="89.8026" y="-547.9955" font-family="Times,serif" font-size="14.00" fill="#000000">viewing status, logs</text>
+</g>
+<!-- webui&#45;&gt;user_friendly -->
+<g id="edge7" class="edge">
+<title>webui&#45;&gt;user_friendly</title>
+<path fill="none" stroke="#000000" d="M57.5029,-526.8623C49.828,-511.098 42.7315,-493.524 38.8026,-476.3991 22.9202,-407.1727 9.4991,-381.2911 38.8026,-316.5929 52.4155,-286.5374 79.3164,-261.6653 104.2035,-243.6551"/>
+<polygon fill="#000000" stroke="#000000" points="106.3617,-246.4167 112.5442,-237.8127 102.3456,-240.6833 106.3617,-246.4167"/>
+</g>
+<!-- self_registration -->
+<g id="node9" class="node">
+<title>self_registration</title>
+<ellipse fill="#00cc00" stroke="#000000" cx="158.8026" cy="-396.496" rx="111.0315" ry="37.4533"/>
+<text text-anchor="middle" x="158.8026" y="-407.796" font-family="Times,serif" font-size="14.00" fill="#000000">Users can create</text>
+<text text-anchor="middle" x="158.8026" y="-392.796" font-family="Times,serif" font-size="14.00" fill="#000000">an account by themselves</text>
+<text text-anchor="middle" x="158.8026" y="-377.796" font-family="Times,serif" font-size="14.00" fill="#000000">via a web browser</text>
+</g>
+<!-- webui&#45;&gt;self_registration -->
+<g id="edge19" class="edge">
+<title>webui&#45;&gt;self_registration</title>
+<path fill="none" stroke="#000000" d="M111.0679,-524.6184C120.7859,-498.5346 132.1553,-468.0186 141.36,-443.3126"/>
+<polygon fill="#000000" stroke="#000000" points="144.6907,-444.3977 144.9023,-433.805 138.1312,-441.9538 144.6907,-444.3977"/>
+</g>
+<!-- self_registration&#45;&gt;user_friendly -->
+<g id="edge8" class="edge">
+<title>self_registration&#45;&gt;user_friendly</title>
+<path fill="none" stroke="#000000" d="M158.8026,-359.0181C158.8026,-326.7316 158.8026,-280.3885 158.8026,-248.2541"/>
+<polygon fill="#000000" stroke="#000000" points="162.3027,-247.9419 158.8026,-237.9419 155.3027,-247.942 162.3027,-247.9419"/>
+</g>
+<!-- worker_tags -->
+<g id="node10" class="node">
+<title>worker_tags</title>
+<ellipse fill="#ffffff" stroke="#000000" cx="953.8026" cy="-581.6955" rx="94.0904" ry="69.0935"/>
+<text text-anchor="middle" x="953.8026" y="-615.4955" font-family="Times,serif" font-size="14.00" fill="#000000">Ick allows projects</text>
+<text text-anchor="middle" x="953.8026" y="-600.4955" font-family="Times,serif" font-size="14.00" fill="#000000">and workers to have</text>
+<text text-anchor="middle" x="953.8026" y="-585.4955" font-family="Times,serif" font-size="14.00" fill="#000000">tags, and can choose</text>
+<text text-anchor="middle" x="953.8026" y="-570.4955" font-family="Times,serif" font-size="14.00" fill="#000000">which worker to give</text>
+<text text-anchor="middle" x="953.8026" y="-555.4955" font-family="Times,serif" font-size="14.00" fill="#000000">an action to, based</text>
+<text text-anchor="middle" x="953.8026" y="-540.4955" font-family="Times,serif" font-size="14.00" fill="#000000">on tags</text>
+</g>
+<!-- worker_tags&#45;&gt;on_demand_workers -->
+<g id="edge17" class="edge">
+<title>worker_tags&#45;&gt;on_demand_workers</title>
+<path fill="none" stroke="#000000" d="M948.3275,-512.4561C941.7815,-457.088 927.5467,-378.7226 896.8026,-316.5929 883.6205,-289.9538 862.1891,-264.4938 843.5463,-245.2836"/>
+<polygon fill="#000000" stroke="#000000" points="845.8233,-242.6093 836.2954,-237.9757 840.8542,-247.5396 845.8233,-242.6093"/>
+</g>
+<!-- worker_tags&#45;&gt;multiarch -->
+<g id="edge9" class="edge">

(Diff truncated)
Publish
diff --git a/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn b/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
index 9b5220e..c64c25e 100644
--- a/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
+++ b/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Rethinking email: the spam problem"]]
 [[!meta date="2020-04-12 12:09"]]
-[[!tag draft email idea]]
+[[!tag email idea]]
 
 I am tired of the existing Internet email system, both as a sender of
 email, as a recipient, and as an operator of an email server.

Fix: add missing links
diff --git a/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn b/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
index ed37a74..9b5220e 100644
--- a/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
+++ b/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
@@ -11,6 +11,9 @@ interested in inspiring more discussion. See [HTML][] and [PDF][]
 versions. It's a bit long, and does not yet address more than the spam
 problem.
 
+[HTML]: https://ideas.liw.fi/rethinking-email.html
+[PDF]: https://ideas.liw.fi/rethinking-email.pdf
+
 TL;DR: I don't think the current email system can be improved enough
 to be worthwhile, but a new system could use digital signatures and
 digital stamps (tokens) to only allow recipients accept mail from

Publish log entry
diff --git a/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn b/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
new file mode 100644
index 0000000..ed37a74
--- /dev/null
+++ b/posts/2020/04/12/rethinking_email_the_spam_problem.mdwn
@@ -0,0 +1,17 @@
+[[!meta title="Rethinking email: the spam problem"]]
+[[!meta date="2020-04-12 12:09"]]
+[[!tag draft email idea]]
+
+I am tired of the existing Internet email system, both as a sender of
+email, as a recipient, and as an operator of an email server.
+
+I've been thinking about ways to solve that, and have written an essay
+about it, without any plans to work on implementing a solution. I'm
+interested in inspiring more discussion. See [HTML][] and [PDF][]
+versions. It's a bit long, and does not yet address more than the spam
+problem.
+
+TL;DR: I don't think the current email system can be improved enough
+to be worthwhile, but a new system could use digital signatures and
+digital stamps (tokens) to only allow recipients accept mail from
+specific senders.

Drop: old version of book club post
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
deleted file mode 100644
index b130acf..0000000
--- a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
+++ /dev/null
@@ -1,86 +0,0 @@
-[[!meta title="Book club: Latacora -- Stop using encrypted email"]]
-[[!meta date="2020-04-11 08:26"]]
-[[!tag book-club email encryption]]
-
-Three friends sat down and discussed a book, er, blog post that they'd
-read: Daniel, Mark, and myself. We live in different countries, so we
-did this over video conferencing. This is a summary of the discussion.
-
-The article:
-<https://latacora.singles/2020/02/19/stop-using-encrypted.html>
-published in February this year. The title is "Stop Using Encrypted
-Email". It's not long.
-
-To start with, we all agree that using encryption with the current
-Internet email system is far from ideal. The blog post correctly
-points out problems:
-
-* email metadata (headers, routing) is public, even on encrypted
-  messages
-* it's easy to reply to an encrypted email in cleartext
-* PGP is far from ideal
-* PGP users tend to have long-lived encryption keys, and that if and
-  when they are broken or leak, all messages' security is at danger
-* personal email archives can leak an encrypted message long after it
-  was sent
-
-However, we think that blog post argues too strongly that encrypted
-email is pointless.
-
-Most importantly, they claim that encrypted email should not be used
-by anyone, ever, for anything. We find this to be too strong, if
-understandable. They don't describe an actual threat model, though
-they give some examples, and seem to mostly concentrate on a threat
-where a very powerful adversary, with pervasive surveillance
-capabilities, is trying to catch individuals so they can punish them,
-and possibly kill them, possibly long after the communication happens.
-That is certainly a threat model where current encrypted email fails.
-
-However, we claim there are situations where the encrypted email works
-well enough. For example, password reset emails that are encrypted to
-the PGP public key registered with the service. The value of the email
-disappears minutes after it's sent.
-
-Or emails preparing a surprise party for someone's spouse. If the
-messages leak, it's a bummer, but it's not a big problem, especially
-after the party is over.
-
-Thus we feel that rather than telling people to not use encrypted
-email at all, for anything, ever, a more sensible and useful approach
-is to discuss the risks and give people tools to decide for
-themselves. Accurate information is more valuable than overblown
-rhetoric, whether it's for or against email encryption.
-
-We agree that the secure messaging systems they promote are good, but
-we don't agree that they're as good as the article implies. Signal,
-for example, routes all traffic through its own servers. A very
-powerful adversary with pervasive surveillance capabilities can deduce
-much from traffic patterns. This has already been used against Tor
-users (see for example [1] and [2]).
-
-[1]: https://securityaffairs.co/wordpress/30202/hacking/tor-traffic-analysis-attack.html
-[2]: https://www.ohmygodel.com/publications/usersrouted-ccs13.pdf
-
-We're also not entirely happy with messaging systems that require the
-use of phone numbers. Signal is one of these. Signal is also
-problematic when changing phones or phone numbers, as all trust
-relationships within it have to be re-established.
-
-Messaging systems are also meant for use cases that aren't all the
-same as email's. For example, offline use, and long-form messages. We
-see messaging systems and email as complementary more than competing.
-
-We also do not agree that improving email security is as hopeless as
-the blog post claims. Much could be done just by improving email
-client software. That said, we repeat that we agree that it's not
-going to be good enough against their implied threat model.
-
-For example, email clients and servers could refuse to send or accept
-email except over unencrypted or unverified channels, or emails that
-are unencrypted. This wouldn't help, say, gmail users, but we would
-not expect people with the blog post's implied threat model to use
-gmail. Or email at all.
-
-In summary, we do think the email system could be improved. We just
-don't think it and its encryption are as useless as the blog post
-claims, and we don't think the blog post is making things better.

Change: add links to book club post, move it to today
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
index c842482..b130acf 100644
--- a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
+++ b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Book club: Latacora -- Stop using encrypted email"]]
-[[!meta date="2020-03-17 08:26"]]
-[[!tag draft book-club email encryption]]
+[[!meta date="2020-04-11 08:26"]]
+[[!tag book-club email encryption]]
 
 Three friends sat down and discussed a book, er, blog post that they'd
 read: Daniel, Mark, and myself. We live in different countries, so we
@@ -42,7 +42,8 @@ the PGP public key registered with the service. The value of the email
 disappears minutes after it's sent.
 
 Or emails preparing a surprise party for someone's spouse. If the
-messages leak, it's a bummer, but it's not a big problem.
+messages leak, it's a bummer, but it's not a big problem, especially
+after the party is over.
 
 Thus we feel that rather than telling people to not use encrypted
 email at all, for anything, ever, a more sensible and useful approach
@@ -55,7 +56,10 @@ we don't agree that they're as good as the article implies. Signal,
 for example, routes all traffic through its own servers. A very
 powerful adversary with pervasive surveillance capabilities can deduce
 much from traffic patterns. This has already been used against Tor
-users. (FIXME: link would be good)
+users (see for example [1] and [2]).
+
+[1]: https://securityaffairs.co/wordpress/30202/hacking/tor-traffic-analysis-attack.html
+[2]: https://www.ohmygodel.com/publications/usersrouted-ccs13.pdf
 
 We're also not entirely happy with messaging systems that require the
 use of phone numbers. Signal is one of these. Signal is also
diff --git a/posts/2020/04/11/book_club.mdwn b/posts/2020/04/11/book_club.mdwn
new file mode 100644
index 0000000..b130acf
--- /dev/null
+++ b/posts/2020/04/11/book_club.mdwn
@@ -0,0 +1,86 @@
+[[!meta title="Book club: Latacora -- Stop using encrypted email"]]
+[[!meta date="2020-04-11 08:26"]]
+[[!tag book-club email encryption]]
+
+Three friends sat down and discussed a book, er, blog post that they'd
+read: Daniel, Mark, and myself. We live in different countries, so we
+did this over video conferencing. This is a summary of the discussion.
+
+The article:
+<https://latacora.singles/2020/02/19/stop-using-encrypted.html>
+published in February this year. The title is "Stop Using Encrypted
+Email". It's not long.
+
+To start with, we all agree that using encryption with the current
+Internet email system is far from ideal. The blog post correctly
+points out problems:
+
+* email metadata (headers, routing) is public, even on encrypted
+  messages
+* it's easy to reply to an encrypted email in cleartext
+* PGP is far from ideal
+* PGP users tend to have long-lived encryption keys, and that if and
+  when they are broken or leak, all messages' security is at danger
+* personal email archives can leak an encrypted message long after it
+  was sent
+
+However, we think that blog post argues too strongly that encrypted
+email is pointless.
+
+Most importantly, they claim that encrypted email should not be used
+by anyone, ever, for anything. We find this to be too strong, if
+understandable. They don't describe an actual threat model, though
+they give some examples, and seem to mostly concentrate on a threat
+where a very powerful adversary, with pervasive surveillance
+capabilities, is trying to catch individuals so they can punish them,
+and possibly kill them, possibly long after the communication happens.
+That is certainly a threat model where current encrypted email fails.
+
+However, we claim there are situations where the encrypted email works
+well enough. For example, password reset emails that are encrypted to
+the PGP public key registered with the service. The value of the email
+disappears minutes after it's sent.
+
+Or emails preparing a surprise party for someone's spouse. If the
+messages leak, it's a bummer, but it's not a big problem, especially
+after the party is over.
+
+Thus we feel that rather than telling people to not use encrypted
+email at all, for anything, ever, a more sensible and useful approach
+is to discuss the risks and give people tools to decide for
+themselves. Accurate information is more valuable than overblown
+rhetoric, whether it's for or against email encryption.
+
+We agree that the secure messaging systems they promote are good, but
+we don't agree that they're as good as the article implies. Signal,
+for example, routes all traffic through its own servers. A very
+powerful adversary with pervasive surveillance capabilities can deduce
+much from traffic patterns. This has already been used against Tor
+users (see for example [1] and [2]).
+
+[1]: https://securityaffairs.co/wordpress/30202/hacking/tor-traffic-analysis-attack.html
+[2]: https://www.ohmygodel.com/publications/usersrouted-ccs13.pdf
+
+We're also not entirely happy with messaging systems that require the
+use of phone numbers. Signal is one of these. Signal is also
+problematic when changing phones or phone numbers, as all trust
+relationships within it have to be re-established.
+
+Messaging systems are also meant for use cases that aren't all the
+same as email's. For example, offline use, and long-form messages. We
+see messaging systems and email as complementary more than competing.
+
+We also do not agree that improving email security is as hopeless as
+the blog post claims. Much could be done just by improving email
+client software. That said, we repeat that we agree that it's not
+going to be good enough against their implied threat model.
+
+For example, email clients and servers could refuse to send or accept
+email except over unencrypted or unverified channels, or emails that
+are unencrypted. This wouldn't help, say, gmail users, but we would
+not expect people with the blog post's implied threat model to use
+gmail. Or email at all.
+
+In summary, we do think the email system could be improved. We just
+don't think it and its encryption are as useless as the blog post
+claims, and we don't think the blog post is making things better.

Change: publish
diff --git a/posts/2020/04/09/contractor_build_software_more_securely.mdwn b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
index 96de7d7..230efce 100644
--- a/posts/2020/04/09/contractor_build_software_more_securely.mdwn
+++ b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Contractor: build software more securely"]]
 [[!meta date="2020-04-09 20:34"]]
-[[!tag draft announcement contractor security programming]]
+[[!tag announcement contractor security programming]]
 
 [Contractor]: https://gitlab.com/larswirzenius/contractor
 

Fix: wording
diff --git a/posts/2020/04/09/contractor_build_software_more_securely.mdwn b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
index f644d06..96de7d7 100644
--- a/posts/2020/04/09/contractor_build_software_more_securely.mdwn
+++ b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
@@ -88,7 +88,7 @@ assume all code involved in the build to be secure. We need something
 more secure. The Contractor aims to be a possible solution.
 
 See the [README][] for instructions how to try it. See [the subplot
-document][] for more information architecture and so on for how it
+document][] for more about the architecture and so on for how it
 works.
 
 [README]: https://gitlab.com/larswirzenius/contractor/-/blob/master/README.md

Change: wording
diff --git a/posts/2020/04/09/contractor_build_software_more_securely.mdwn b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
index 5a53ccc..f644d06 100644
--- a/posts/2020/04/09/contractor_build_software_more_securely.mdwn
+++ b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
@@ -13,7 +13,7 @@ Software development is a security risk.
 
 Building software from source code and running it is a core activity
 of software development. Software developers do it on the machine they
-work on. The process is roughly as follows:
+use for other things too. The process is roughly as follows:
 
 * install any dependencies
 * build the software

Change: emphasais tldr
diff --git a/posts/2020/04/09/contractor_build_software_more_securely.mdwn b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
index 87f3197..5a53ccc 100644
--- a/posts/2020/04/09/contractor_build_software_more_securely.mdwn
+++ b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
@@ -4,7 +4,7 @@
 
 [Contractor]: https://gitlab.com/larswirzenius/contractor
 
-TL;DR: I wrote a little program to build and test software in a pair
+**TL;DR:** I wrote a little program to build and test software in a pair
 of nested virtual machines, to reduce the risk of bugs or malware in
 dependencies doing bad things. It's called the [Contractor][] and it's
 just barely usable now. Feedback welcome.

Add: end text
diff --git a/posts/2020/04/09/contractor_build_software_more_securely.mdwn b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
index 7f5f65f..87f3197 100644
--- a/posts/2020/04/09/contractor_build_software_more_securely.mdwn
+++ b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
@@ -93,3 +93,8 @@ works.
 
 [README]: https://gitlab.com/larswirzenius/contractor/-/blob/master/README.md
 [the subplot document]: https://gitlab.com/larswirzenius/contractor/-/blob/master/contractor.md
+
+The Contractor has only just reached a state where it can build and
+test some of my other projects. It's ugly, buggy, and awkward, but I
+expect to have much fun using and improving it in the future. Maybe
+you'd like to join the adventure?

creating tag page tag/contractor
diff --git a/tag/contractor.mdwn b/tag/contractor.mdwn
new file mode 100644
index 0000000..d2b4c17
--- /dev/null
+++ b/tag/contractor.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged contractor"]]
+
+[[!inline pages="tagged(contractor)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/04/09/contractor_build_software_more_securely.mdwn b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
new file mode 100644
index 0000000..7f5f65f
--- /dev/null
+++ b/posts/2020/04/09/contractor_build_software_more_securely.mdwn
@@ -0,0 +1,95 @@
+[[!meta title="Contractor: build software more securely"]]
+[[!meta date="2020-04-09 20:34"]]
+[[!tag draft announcement contractor security programming]]
+
+[Contractor]: https://gitlab.com/larswirzenius/contractor
+
+TL;DR: I wrote a little program to build and test software in a pair
+of nested virtual machines, to reduce the risk of bugs or malware in
+dependencies doing bad things. It's called the [Contractor][] and it's
+just barely usable now. Feedback welcome.
+
+Software development is a security risk.
+
+Building software from source code and running it is a core activity
+of software development. Software developers do it on the machine they
+work on. The process is roughly as follows:
+
+* install any dependencies
+* build the software
+* run the software, perhaps as part of unit testing
+
+When the software is run, even if only a small unit of it, it can do
+anything that the person running the build can do, in principle:
+
+* delete files
+* modify files
+* log into remote hosts using SSH
+* decrypt or sign files with PGP
+* send email
+* delete email
+* commit to version control repositories
+* do anything with the browser that a the person could do
+* run things as sudo
+* in general, cause mayhem and chaos
+
+Normally, a software developer can assume that the code they wrote
+themselves doesn't do any of that. They can even assume that people
+they work with don't do any of that. In both cases, they may be wrong:
+mistakes happen. It's a well-guarded secret among programmers that
+they sometimes, even if rarely, make catastrophic mistakes.
+
+Accidents aside, mayhem and chaos may be intentional. Your own project
+may not have malware, and you may have vetted all your dependencies,
+and you trust them. But your dependencies have dependencies, which
+have further dependencies, which have dependencies of their own. You'd
+need to vet the whole dependency tree. Even decades ago, in the 1990s,
+this could easily be hundreds of thousands of lines of code, and
+modern systems a much larger. Note that build tools are themselves
+dependencies, as is the whole operating system. Any code that is used
+in the build process is a dependency.
+
+How certain are you that you can spot malicious code that's
+intentionally hidden and obfuscated?
+
+Are you prepared to vet any changes to any transitive dependencies?
+
+Does this really matter? Maybe it doesn't. If you can't ever do
+anything on your computer that would affect you or anyone else in a
+negative way, it probably doesn't matter. Most software developers are
+not in that position.
+
+This risk affects every operating system and every programming
+language. The degree in which it exists varies, a lot. Some
+programming language ecosystems seem more vulnerable than others: the
+nodejs/npm one, for example, values tiny and highly focused packages,
+which leads to immense dependency trees. The more direct or indirect
+dependencies there are, the higher the chance that one of them turns
+out to be bad.
+
+The risk also exists for more traditional languages, such as C. Few C
+programs have no dependencies. They all need a C compiler, which in
+turn requires an operating system, at least.
+
+The risk is there for both free software systems, and non-free ones.
+As an example, the Debian system is entirely free software, but it's
+huge: the Debian 10 (buster) release has tens of thousands of software
+packages, maintained by thousands of people. While it's probable that
+none of those packages contains actual malware, it's not certain. Even
+if everyone who helps maintain is completely trustworthy, the amount
+of software in Debian is much too large for all code to be
+comprehensively reviewed. Also, no amount of review will catch all
+bugs.
+
+This is true for all operating systems that are not mere toys.
+
+The conclusion here is that to build software securely, we can't
+assume all code involved in the build to be secure. We need something
+more secure. The Contractor aims to be a possible solution.
+
+See the [README][] for instructions how to try it. See [the subplot
+document][] for more information architecture and so on for how it
+works.
+
+[README]: https://gitlab.com/larswirzenius/contractor/-/blob/master/README.md
+[the subplot document]: https://gitlab.com/larswirzenius/contractor/-/blob/master/contractor.md

Fix: email -> gmail
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
index 98b73eb..c842482 100644
--- a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
+++ b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
@@ -73,7 +73,7 @@ going to be good enough against their implied threat model.
 
 For example, email clients and servers could refuse to send or accept
 email except over unencrypted or unverified channels, or emails that
-are unencrypted. This wouldn't help, say, email users, but we would
+are unencrypted. This wouldn't help, say, gmail users, but we would
 not expect people with the blog post's implied threat model to use
 gmail. Or email at all.
 

Fix: spellos
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
index c842482..98b73eb 100644
--- a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
+++ b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
@@ -73,7 +73,7 @@ going to be good enough against their implied threat model.
 
 For example, email clients and servers could refuse to send or accept
 email except over unencrypted or unverified channels, or emails that
-are unencrypted. This wouldn't help, say, gmail users, but we would
+are unencrypted. This wouldn't help, say, email users, but we would
 not expect people with the blog post's implied threat model to use
 gmail. Or email at all.
 

Add: another example of when email encryption is OK
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
index 2960169..c842482 100644
--- a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
+++ b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
@@ -41,6 +41,9 @@ well enough. For example, password reset emails that are encrypted to
 the PGP public key registered with the service. The value of the email
 disappears minutes after it's sent.
 
+Or emails preparing a surprise party for someone's spouse. If the
+messages leak, it's a bummer, but it's not a big problem.
+
 Thus we feel that rather than telling people to not use encrypted
 email at all, for anything, ever, a more sensible and useful approach
 is to discuss the risks and give people tools to decide for

Fix: typos
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
index bb52bfa..2960169 100644
--- a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
+++ b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
@@ -18,9 +18,9 @@ points out problems:
 * email metadata (headers, routing) is public, even on encrypted
   messages
 * it's easy to reply to an encrypted email in cleartext
-* PGP is far from ideal 
+* PGP is far from ideal
 * PGP users tend to have long-lived encryption keys, and that if and
-  when they are broken or leak, many messages' security is at danger
+  when they are broken or leak, all messages' security is at danger
 * personal email archives can leak an encrypted message long after it
   was sent
 

creating tag page tag/encryption
diff --git a/tag/encryption.mdwn b/tag/encryption.mdwn
new file mode 100644
index 0000000..60898b2
--- /dev/null
+++ b/tag/encryption.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged encryption"]]
+
+[[!inline pages="tagged(encryption)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/book-club
diff --git a/tag/book-club.mdwn b/tag/book-club.mdwn
new file mode 100644
index 0000000..5ecd6b7
--- /dev/null
+++ b/tag/book-club.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged book-club"]]
+
+[[!inline pages="tagged(book-club)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
new file mode 100644
index 0000000..bb52bfa
--- /dev/null
+++ b/posts/2020/03/17/book_club_latacora_--_stop_using_encrypted_email.mdwn
@@ -0,0 +1,79 @@
+[[!meta title="Book club: Latacora -- Stop using encrypted email"]]
+[[!meta date="2020-03-17 08:26"]]
+[[!tag draft book-club email encryption]]
+
+Three friends sat down and discussed a book, er, blog post that they'd
+read: Daniel, Mark, and myself. We live in different countries, so we
+did this over video conferencing. This is a summary of the discussion.
+
+The article:
+<https://latacora.singles/2020/02/19/stop-using-encrypted.html>
+published in February this year. The title is "Stop Using Encrypted
+Email". It's not long.
+
+To start with, we all agree that using encryption with the current
+Internet email system is far from ideal. The blog post correctly
+points out problems:
+
+* email metadata (headers, routing) is public, even on encrypted
+  messages
+* it's easy to reply to an encrypted email in cleartext
+* PGP is far from ideal 
+* PGP users tend to have long-lived encryption keys, and that if and
+  when they are broken or leak, many messages' security is at danger
+* personal email archives can leak an encrypted message long after it
+  was sent
+
+However, we think that blog post argues too strongly that encrypted
+email is pointless.
+
+Most importantly, they claim that encrypted email should not be used
+by anyone, ever, for anything. We find this to be too strong, if
+understandable. They don't describe an actual threat model, though
+they give some examples, and seem to mostly concentrate on a threat
+where a very powerful adversary, with pervasive surveillance
+capabilities, is trying to catch individuals so they can punish them,
+and possibly kill them, possibly long after the communication happens.
+That is certainly a threat model where current encrypted email fails.
+
+However, we claim there are situations where the encrypted email works
+well enough. For example, password reset emails that are encrypted to
+the PGP public key registered with the service. The value of the email
+disappears minutes after it's sent.
+
+Thus we feel that rather than telling people to not use encrypted
+email at all, for anything, ever, a more sensible and useful approach
+is to discuss the risks and give people tools to decide for
+themselves. Accurate information is more valuable than overblown
+rhetoric, whether it's for or against email encryption.
+
+We agree that the secure messaging systems they promote are good, but
+we don't agree that they're as good as the article implies. Signal,
+for example, routes all traffic through its own servers. A very
+powerful adversary with pervasive surveillance capabilities can deduce
+much from traffic patterns. This has already been used against Tor
+users. (FIXME: link would be good)
+
+We're also not entirely happy with messaging systems that require the
+use of phone numbers. Signal is one of these. Signal is also
+problematic when changing phones or phone numbers, as all trust
+relationships within it have to be re-established.
+
+Messaging systems are also meant for use cases that aren't all the
+same as email's. For example, offline use, and long-form messages. We
+see messaging systems and email as complementary more than competing.
+
+We also do not agree that improving email security is as hopeless as
+the blog post claims. Much could be done just by improving email
+client software. That said, we repeat that we agree that it's not
+going to be good enough against their implied threat model.
+
+For example, email clients and servers could refuse to send or accept
+email except over unencrypted or unverified channels, or emails that
+are unencrypted. This wouldn't help, say, gmail users, but we would
+not expect people with the blog post's implied threat model to use
+gmail. Or email at all.
+
+In summary, we do think the email system could be improved. We just
+don't think it and its encryption are as useless as the blog post
+claims, and we don't think the blog post is making things better.

Fix: typos
diff --git a/posts/2020/03/09/godwin_on_empowering_people.mdwn b/posts/2020/03/09/godwin_on_empowering_people.mdwn
index 2ea57d4..8c1d106 100644
--- a/posts/2020/03/09/godwin_on_empowering_people.mdwn
+++ b/posts/2020/03/09/godwin_on_empowering_people.mdwn
@@ -2,7 +2,7 @@
 [[!meta date="2020-03-09 09:35"]]
 [[!tag godwin wikipedia empowering]]
 
-Mike Godwin in essay on
+Mike Godwin in an essay on
 [slate.com](https://slate.com/technology/2020/02/three-decades-internet-freedom-activism.html):
 
 > That’s the biggest thing I learned at the Wikimedia Foundation: When
@@ -16,4 +16,4 @@ Mike Godwin in essay on
 > we dutifully have to bear. Now, more than I ever did 30 years ago, I
 > argue that it’s the solution.
 
-I though that was well said.
+I thought that was well said.

creating tag page tag/empowering
diff --git a/tag/empowering.mdwn b/tag/empowering.mdwn
new file mode 100644
index 0000000..f1a6668
--- /dev/null
+++ b/tag/empowering.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged empowering"]]
+
+[[!inline pages="tagged(empowering)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/godwin
diff --git a/tag/godwin.mdwn b/tag/godwin.mdwn
new file mode 100644
index 0000000..0829f39
--- /dev/null
+++ b/tag/godwin.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged godwin"]]
+
+[[!inline pages="tagged(godwin)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/wikipedia
diff --git a/tag/wikipedia.mdwn b/tag/wikipedia.mdwn
new file mode 100644
index 0000000..a74cf29
--- /dev/null
+++ b/tag/wikipedia.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged wikipedia"]]
+
+[[!inline pages="tagged(wikipedia)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/03/09/godwin_on_empowering_people.mdwn b/posts/2020/03/09/godwin_on_empowering_people.mdwn
new file mode 100644
index 0000000..2ea57d4
--- /dev/null
+++ b/posts/2020/03/09/godwin_on_empowering_people.mdwn
@@ -0,0 +1,19 @@
+[[!meta title="Godwin on empowering people"]]
+[[!meta date="2020-03-09 09:35"]]
+[[!tag godwin wikipedia empowering]]
+
+Mike Godwin in essay on
+[slate.com](https://slate.com/technology/2020/02/three-decades-internet-freedom-activism.html):
+
+> That’s the biggest thing I learned at the Wikimedia Foundation: When
+> ordinary people are empowered to come together and work on a common,
+> humanity-benefiting project like Wikipedia, unexpectedly great and
+> positive things can happen. Wikipedia is not the anomaly my
+> journalist friend thinks it is. Instead, it’s a promise of the good
+> works that ordinary people freed by the internet can create. I no
+> longer argue primarily that the explosion of freedom of expression
+> and diverse voices, facilitated by the internet, is simply a burden
+> we dutifully have to bear. Now, more than I ever did 30 years ago, I
+> argue that it’s the solution.
+
+I though that was well said.

creating tag page tag/email
diff --git a/tag/email.mdwn b/tag/email.mdwn
new file mode 100644
index 0000000..c7295f6
--- /dev/null
+++ b/tag/email.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged email"]]
+
+[[!inline pages="tagged(email)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn b/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn
new file mode 100644
index 0000000..5f25a66
--- /dev/null
+++ b/posts/2020/03/08/what_people_like_or_hate_about_email.mdwn
@@ -0,0 +1,67 @@
+[[!meta title="What people like or hate about email"]]
+[[!meta date="2020-03-08 09:33"]]
+[[!tag email]]
+
+I [asked a couple of weeks
+ago](https://toot.liw.fi/@liw/103729502946243759) what people like or
+hate about email. Here's a summary of the responses. I admit the
+summary may be tainted by my current thinking about [re-inventing
+email](https://ideas.liw.fi/email2.html).
+
+# Like
+
+* It's not real time. Sender and recipient do not net need to be
+  participating in the communication at the same time. The sender can
+  take their time to craft their message, the recipient can take their
+  time to ponder on the message and how to respond.
+
+* It's established, ubiquitous.
+
+* It's de-centralized.
+
+* It's built on top of well-known data formats and protocols, and data
+  can be stored locally under user control, and is highly portable.
+  There are a variety of client software to choose from.
+
+* Separate discussions are kept separate.
+
+* Formatting, attachments, and lenght is flexible.
+
+* Mailing lists can be archived publically.
+
+* One can have many accounts, and people comprehend this.
+
+* Subject lines.
+
+* Email providers are neutral, commodity entities. Choosing one
+  doesn't imply membership in a community.
+
+# Not like
+
+* Unreliable for communication, often due to bad anti-spam.
+
+* People sending one-line replies that don't add actual value or that
+  miss the point entirely.
+
+* Encryption, security, privacy, rich media content, formatted
+  messages, etc, are all built on top of older protocols, often
+  resulting in unfortunate consequences.
+
+* Top quoting.
+
+* De-facto oligopoly.
+
+* Spam.
+
+* Abuse.
+
+* Configuring and administering email servers is complex.
+
+* Filters and organisation of email is often difficult. The tools
+  provided are not always well suited for the task.
+
+* Threading is unreliable.
+
+* Email addresses are too tightly tied to your identity.
+
+* Searching is often inadequate.

Publish log entry
diff --git a/posts/2020/03/07/demo_site_for_how_i_journal.mdwn b/posts/2020/03/07/demo_site_for_how_i_journal.mdwn
new file mode 100644
index 0000000..1601c24
--- /dev/null
+++ b/posts/2020/03/07/demo_site_for_how_i_journal.mdwn
@@ -0,0 +1,22 @@
+[[!meta title="Demo site for how I journal"]]
+[[!meta date="2020-03-07 11:32"]]
+[[!tag ]]
+
+A friend expressed interest in how I keep my journal, so I set up a
+demo site. In short:
+
+* markdown files (mostly) in git
+* [ikiwiki][] renders to HTML (locally or via CI to a website)
+  - ikiwiki's [inline][] directive helps collect journal entries
+  - tags and topic pages help collect
+  - I have a "topic" for each person
+* [jt][] helps make entries and maintain the journal (not necessary,
+  but relieves some tedium)
+
+[ikiwiki]: http://ikiwiki.info/
+[inline]: http://ikiwiki.info/ikiwiki/directive/inline/
+[jt]: http://git.liw.fi/jt
+
+* source: <http://git.liw.fi/demo-journal>
+* rendered: <http://demo-journal.liw.fi/>
+* instructions: <http://git.liw.fi/demo-journal/tree/README.md>

Fix: typo
diff --git a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
index be015dc..2b1683a 100644
--- a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
+++ b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
@@ -2,7 +2,7 @@
 [[!meta title="Alternative Debian installer based on vmdb2: v-i"]]
 [[!tag vmdb2 v-i debian]]
 
-I wrote an alterantive Debian installer as a toy, called v-i. One of
+I wrote an alternative Debian installer as a toy, called v-i. One of
 the following two bullet points is correct:
 
 * v-i can install a very rudimentary Debian onto exactly one computer

Fix: missing word
diff --git a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
index 109a921..be015dc 100644
--- a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
+++ b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
@@ -30,7 +30,7 @@ things I wanted to change:
   special udeb packages for any software that's to be part of the
   installer. v-i is happy with normal debs.
 
-* Debian in general preseeding for automating an installation.
+* Debian in general uses preseeding for automating an installation.
   Preseeding means providing answers, in a file, to questions the
   package may ask during its installation. This is fine, if a little
   cumbersome, but only helps when the packages ask the right

Change: publish
diff --git a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
index 5dbc9c2..109a921 100644
--- a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
+++ b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
@@ -1,6 +1,6 @@
 [[!meta date="2020-02-29 20:12"]]
 [[!meta title="Alternative Debian installer based on vmdb2: v-i"]]
-[[!tag draft vmdb2 v-i debian]]
+[[!tag vmdb2 v-i debian]]
 
 I wrote an alterantive Debian installer as a toy, called v-i. One of
 the following two bullet points is correct:
@@ -68,4 +68,5 @@ PS. A 128 GB USB3 flash drive can be had for as little as 20 euros,
 and that has enough disk space for v-i and a Debian mirror.
 
 If you want to respond to this blog post, please email me (liw@liw.fi)
-or respond to [this fediverse post]().
+or respond to [this fediverse
+post](https://toot.liw.fi/@liw/103743493062316650).

creating tag page tag/v-i
diff --git a/tag/v-i.mdwn b/tag/v-i.mdwn
new file mode 100644
index 0000000..fa94165
--- /dev/null
+++ b/tag/v-i.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged v-i"]]
+
+[[!inline pages="tagged(v-i)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
new file mode 100644
index 0000000..5dbc9c2
--- /dev/null
+++ b/posts/2020/02/29/alternative_debian_installer_based_on_vmdb2_v-i.mdwn
@@ -0,0 +1,71 @@
+[[!meta date="2020-02-29 20:12"]]
+[[!meta title="Alternative Debian installer based on vmdb2: v-i"]]
+[[!tag draft vmdb2 v-i debian]]
+
+I wrote an alterantive Debian installer as a toy, called v-i. One of
+the following two bullet points is correct:
+
+* v-i can install a very rudimentary Debian onto exactly one computer
+  in the world: my very own spare Thinkpad x220 laptop. It might not
+  work on your x220. v-i almost certainly won't work on any other kind
+  of computer. If you try, it will probably delete all your data. Make
+  sure your backups work.
+
+* v-i is perfect in every way. There are not even any typos in the
+  manual. There are no bugs, and all features are fully implemented.
+  Every possible use case is supported. Not only is there no danger to
+  your data, v-i will prevent it from ever disappering. Even your
+  hardware will never break again. Your laptop will have infinite
+  battery life, and your screen resolution will require 64 bit
+  integers to express.
+
+[vmdb2]: https://vmdb2.liw.fi/
+
+The v-i installer is based on the [vmdb2][] tool, which I also wrote.
+It has nothing to do with debian-installer, which is the official
+Debian installer, also known as d-i. I use d-i, but have a couple of
+things I wanted to change:
+
+* I'd like something I can easily modify. d-i requires building
+  special udeb packages for any software that's to be part of the
+  installer. v-i is happy with normal debs.
+
+* Debian in general preseeding for automating an installation.
+  Preseeding means providing answers, in a file, to questions the
+  package may ask during its installation. This is fine, if a little
+  cumbersome, but only helps when the packages ask the right
+  questions. v-i lets you have the full power of Ansible during
+  initial installation, which is much more flexible.
+
+On the other hand, d-i is mature software and tested by a very large
+number of people, on a very large number of different hardware. v-i
+is not. v-i might, at best, be the beginning of something useful for a
+small number of people.
+
+I can now install Debian onto my x220 with v-i. It's a very basic
+install, without LVM2, full-disk encryption, or a graphical desktop,
+but it does have sshd and I can configure the laptop further with
+Ansible from another host. I've installed the GNOME desktop that way,
+after rebooting into a v-i installed system. (In theory, I could
+install GNOME directly from v-i. In practice, there are bugs in
+packages and/or how vmdb2 runs Ansible.)
+
+The installed system is also highly configured to my needs and
+preferences. It uses Finnish locales, and requires my SSH key to log
+in. The root account has no password. All of this could be made better
+with a bit of work.
+
+The code is at <https://gitlab.com/larswirzenius/v-i>. Check the
+README for more instructions if you're curious. If you do give it a
+try, I'd love to hear from you, unless you just lost all your data.
+Please don't lose all your data.
+
+If you'd like to help build a more viable installer from v-i, please
+talk to me. I dream of a future where I can install a bare metal
+machine as easily as I can create and configure a VM. 
+
+PS. A 128 GB USB3 flash drive can be had for as little as 20 euros,
+and that has enough disk space for v-i and a Debian mirror.
+
+If you want to respond to this blog post, please email me (liw@liw.fi)
+or respond to [this fediverse post]().

Change: publish
diff --git a/posts/2020/02/28/security_isolation_in_ci_engines.mdwn b/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
index 65653c1..fa6beaf 100644
--- a/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
+++ b/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Security isolation in CI engines"]]
 [[!meta date="2020-02-28 09:28"]]
-[[!tag draft ick continuous-integration security]]
+[[!tag ick continuous-integration security]]
 
 A continuous integration engine (CI) takes the source code for a
 software project and ensures it works. In less abstract terms, it
@@ -106,5 +106,5 @@ HTTPS proxy may need to be enough.
 What threat am I missing? Are my mitigations acceptable?
 
 If you want to comment on this blog post, please send me email
-(liw@liw.fi), or respond on the fediverse on [this thread](). Thank
-you!
+(liw@liw.fi), or respond on the fediverse on [this
+thread](https://toot.liw.fi/@liw/103735557747821512). Thank you!

Fix? typo
diff --git a/posts/2020/02/28/security_isolation_in_ci_engines.mdwn b/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
index 7690cbb..65653c1 100644
--- a/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
+++ b/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
@@ -73,7 +73,7 @@ My current plan for mitigating all of the above looks as follows:
 * the inner VM can be any operating system, as long as it can run as a
   Qemu/KVM guest, and provides ssh access from the outer VM
 * the manager runs commands on the builder over ssh, or possibly via
-  serial consoler (ssh would be simpler, though)
+  serial console (ssh would be simpler, though)
 * both VMs have a restricted amount of CPUs, RAM, disk space
 * the manager monitors the builder's use of CPU time, bandwidth use
 * the manager proxies and firewalls all outgoing network access to

creating tag page tag/security
diff --git a/tag/security.mdwn b/tag/security.mdwn
new file mode 100644
index 0000000..d42e5e2
--- /dev/null
+++ b/tag/security.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged security"]]
+
+[[!inline pages="tagged(security)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2020/02/28/security_isolation_in_ci_engines.mdwn b/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
new file mode 100644
index 0000000..7690cbb
--- /dev/null
+++ b/posts/2020/02/28/security_isolation_in_ci_engines.mdwn
@@ -0,0 +1,110 @@
+[[!meta title="Security isolation in CI engines"]]
+[[!meta date="2020-02-28 09:28"]]
+[[!tag draft ick continuous-integration security]]
+
+A continuous integration engine (CI) takes the source code for a
+software project and ensures it works. In less abstract terms, it
+builds it, and runs any automated tests it may have. The exact steps
+for that depend heavily on the CI engine and the project, but can be
+thought of as follows (with concrete examples of possible commands):
+
+* retrieve the desired revision of the source code (git clone, git
+  checkout)
+* install build dependencies (dpkg-checkbuilddeps, apt install)
+* build (./configure, make)
+* test (make check)
+
+This is dangerous stuff. In the specific case of an open, hosted CI
+service, it's especially dangerous: anyone can submit any build, and
+that build can do anything, including attack computers anywhere on the
+Internet. However, even in a CI engine that only builds projects for
+in-house developers, it's risky: most attacks on IT are done by
+insiders.
+
+Apart from actual attacks, building software is dangerous also due to
+accidents: a mistake in the way software is built, or automatically
+tested, can result in what looks and behaves like an attack. An
+infinite loop can use excessive amounts of CPU resources, or block
+other projects from getting built.
+
+I've been thinking about ways to deal with this, in the context of
+developing a CI engine, and here's a list of specific threats I've
+come up with:
+
+* excessive use build host resources
+  * e.g., CPU, GPU, RAM, disk, etc
+  * mitigation: use quotas or other hard limits that can't be exceeded
+    (e.g., dedicated file system for build, virtual machine with a
+    virtual memory limit)
+  * mitigation: monitor use, stop build if use goes over a limit, if a
+    quota is infeasible (e.g., CPU time)
+* excessive use of network bandwidth
+  * mitigation: monitor use, stop build if it goes over a limit
+* attack on a networked target via a denial of service attack
+  * e.g., build joins a DDoS swarm, or sends fabricated SYN packets to
+    prevent target from working
+  * mitigation: prevent direct network access for build, force all
+    outgoing connections to go via a proxy that validates requests and
+    stops build if anything looks suspicious
+* attack on build host, or other host, via network intrusion
+  * e.g., port scanning, probing for known vulnerabilities
+  * mitigation: prevent direct network access for build, force all
+    outgoing connections to go via a proxy that validates requests and
+    stops build if anything looks suspicious
+* attack build host directly without network
+  * e.g., by breaching security isolation using build host kernel or
+    hardware vulnerabilities, or CI engine vulnerabilities
+  * this includes eavesdropping on the host, and stealing secrets
+  * mitigation: keep build host up to date on security updates
+  * mitigation: run build inside a VM controlled by CI engine (on the
+    assumption that a VM provides better security isolation than a
+    Linux container)
+
+I'm sure this is not an exhaustive list. If you can think of
+additional risks, do tell me.
+
+My current plan for mitigating all of the above looks as follows:
+
+* there are two, nested virtual machines
+* the outer VM is the manager, the inner VM is the builder
+* the manager creates, controls, monitors, and destroys the builder
+* the outer VM is probably Debian Linux, since that what I know best,
+  using libvirt with Qemu and KVM to manage the inner VM
+* the inner VM can be any operating system, as long as it can run as a
+  Qemu/KVM guest, and provides ssh access from the outer VM
+* the manager runs commands on the builder over ssh, or possibly via
+  serial consoler (ssh would be simpler, though)
+* both VMs have a restricted amount of CPUs, RAM, disk space
+* the manager monitors the builder's use of CPU time, bandwidth use
+* the manager proxies and firewalls all outgoing network access to
+  prevent any access that isn't explicitly allowed
+
+To look at the build steps from the top of this article, they would
+work something like this:
+
+* retrieve the desired revision of the source code: the builder does
+  this, but proxied via the manager, which checks that
+  only from servers listed as allowed for this project are connected
+* install build dependencies: the builder downloads the build
+  dependencies, but proxied via the manager, which checks that
+  downloads come only from servers listed as allowed for this project
+* build: runs inside the builder
+* test: runs inside the builder
+
+It would be awesome if the manager could disable the builder from
+having network access after build dependencies are installed. This
+would be feasible if the build recipe is structured in a way that
+allows the manager to know what part is doing what. (If I'm designing
+the CI engine, then I can probably achieve that.)
+
+It would be even more awesome if the manager could do all the
+downloading, but given the guest may need to use tools specific for
+its operating system, which might not be available on the operating
+system of the manager, this might not be feasible. A filtering HTTP or
+HTTPS proxy may need to be enough.
+
+What threat am I missing? Are my mitigations acceptable?
+
+If you want to comment on this blog post, please send me email
+(liw@liw.fi), or respond on the fediverse on [this thread](). Thank
+you!

Publish
diff --git a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
index c8c0696..57705f7 100644
--- a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
+++ b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Subplot volunteers? (Acceptance testing tool)"]]
 [[!meta date="2020-02-15 18:48"]]
-[[!tag subplot announcement draft]]
+[[!tag subplot announcement]]
 
 [Subplot]: https://subplot.liw.fi/
 [yarn]: https://liw.fi/cmdtest/

Change: scenario typesetting
diff --git a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
index 47bccc8..c8c0696 100644
--- a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
+++ b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
@@ -14,9 +14,9 @@ Would you be willing to try Subplot for acceptance testing for one of
 your real projects, and give us feedback? We're looking for two
 volunteers.
 
-> given a project  
-> when it uses Subplot  
-> then it is successful
+> *given* a project  
+> *when* it uses Subplot  
+> *then* it is successful
 
 [Subplot][] is a tool for capturing and automatically verifying the
 acceptance criteria for a software project or a system, in a way

Change: style for kitten photo
diff --git a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
index f8e9d2c..47bccc8 100644
--- a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
+++ b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
@@ -8,7 +8,7 @@
 [Lars Wirzenius]: https://liw.fi/
 [Daniel Silverstone]: https://blog.digital-scurf.org/
 
-[[!img kitten.jpg]]
+[[!img kitten.jpg class=floatTR]]
 
 Would you be willing to try Subplot for acceptance testing for one of
 your real projects, and give us feedback? We're looking for two

Add: kitten photo
diff --git a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool/kitten.jpg b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool/kitten.jpg
new file mode 100644
index 0000000..837a8cd
Binary files /dev/null and b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool/kitten.jpg differ

Publish log entry
diff --git a/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
new file mode 100644
index 0000000..f8e9d2c
--- /dev/null
+++ b/posts/2020/02/15/subplot_volunteers_acceptance_testing_tool.mdwn
@@ -0,0 +1,91 @@
+[[!meta title="Subplot volunteers? (Acceptance testing tool)"]]
+[[!meta date="2020-02-15 18:48"]]
+[[!tag subplot announcement draft]]
+
+[Subplot]: https://subplot.liw.fi/
+[yarn]: https://liw.fi/cmdtest/
+[gitlab.com]: https://gitlab.com/larswirzenius/subplot
+[Lars Wirzenius]: https://liw.fi/
+[Daniel Silverstone]: https://blog.digital-scurf.org/
+
+[[!img kitten.jpg]]
+
+Would you be willing to try Subplot for acceptance testing for one of
+your real projects, and give us feedback? We're looking for two
+volunteers.
+
+> given a project  
+> when it uses Subplot  
+> then it is successful
+
+[Subplot][] is a tool for capturing and automatically verifying the
+acceptance criteria for a software project or a system, in a way
+that's understood by all stakeholders.
+
+In a software project there are always more than one stakeholder. Even
+in a project one writes for oneself, there are two stakeholders:
+oneself, and that malicious cretin oneself-in-the-future. More
+importantly, though, there are typically stakeholders such as end
+users, sysadmins, clients, software architects, developers, and
+testers. They all need to understand what the software should do, and
+when it's in an acceptable state to be put into use: in other words,
+what the acceptance criteria are.
+
+Crucially, all stakeholders should understand the acceptance criteria
+the same way, and also how to verify they are met. In an ideal
+situation, all verification is automated, and happens very frequently.
+
+There are various tools for this, from generic documentation tooling
+(word processors, text editors, markup languages, etc) to test
+automation (Cucumber, Selenium, etc). On the one hand, documenting
+acceptance criteria in a way that all stakeholders understand is
+crucial: otherwise the end users are at risk of getting something
+that's not useful to help them, and the project is a waste of
+everyone's time and money. On the other hand, automating the
+verification of how acceptance criteria is met is also crucial:
+otherwise it's done manually, which is slow, costly, and error prone,
+which increases the risk of project failure.
+
+Subplot aims to solve this by an approach that combines documentation
+tooling with automated verification.
+
+* The stakeholders in a project jointly produce a document that
+  captures all relevant acceptance criteria and also describes how
+  they can be verified automatically, using scenarios. The document is
+  written using Markdown.
+
+* The developer stakeholders produce code to implement the steps in
+  the scenarios. The Subplot approach allows the step implementations
+  to be done in a highly cohesive, de-coupled manner, making such code
+  usually be quite simple. (Test code should be your best code.)
+
+* Subplot's "docgen" program produces a typeset version as PDF or
+  HTML. This is meant to be easily comprehensible by all stakeholders.
+
+* Subplot's "codegen" program produces a test program in the language
+  used by the developer stakeholders. This test program can be run to
+  verify that acceptance criteria are met.
+
+Subplot started in in late 2018, and was initially called Fable. It is
+based on the [yarn][] tool for the same purpose, from 2013. Yarn has
+been in active use all its life, if not popular outside a small
+circle. Subplot improves on yarn by improving document generation,
+markup, and decoupling of concerns. Subplot is not compatible with
+yarn.
+
+Subplot is developed by [Lars Wirzenius][] and [Daniel Silverstone][]
+as a hobby project. It is free software, implemented in Rust,
+developed on Debian, and uses Pandoc and LaTeX for typesetting. The
+code is hosted on [gitlab.com][]. Subplot verifies its own acceptance
+criteria. It is alpha level software.
+
+We're looking for one or two volunteers to try Subplot on real
+projects of their own, and give us feedback. We want to make Subplot
+good for its purpose, also for people other than us. If you'd be
+willing to give it a try, start with the [Subplot][] website, then
+tell us you're using Subplot. We're happy to respond to questions from
+the first two volunteers, and from others, time permitting. (The
+reality of life and time constraints is that we can't commit to
+supporting more people at this time.)
+
+We'd love your feedback, whether you use Subplot or not.

Publish log entry
diff --git a/posts/2019/12/21/why_debian_isn_t_fun_for_me.mdwn b/posts/2019/12/21/why_debian_isn_t_fun_for_me.mdwn
new file mode 100644
index 0000000..2ae3bd8
--- /dev/null
+++ b/posts/2019/12/21/why_debian_isn_t_fun_for_me.mdwn
@@ -0,0 +1,32 @@
+[[!meta title="Why Debian isn't fun for me"]]
+[[!meta date="2019-12-21 10:13"]]
+[[!tag debian]]
+
+I retired from Debian as a developer a year ago. I said then that it
+was because Debian wasn't fun anymore, but I didn't unpack that much.
+It's been long enough that I feel I can do that. I should've done it
+back then, but I wasn't strong enough.
+
+A big part of Debian not being fun is that there's so much hatred in
+the project. There's people attacking others for who they are, be it
+women or trans or non-binary. There's people standing up to defend the
+attackers. Debian is just now going through another bout of that. It's
+sad and it's disgusting. And it reaffirms that I made the right
+decision getting out.
+
+[bout]: https://lists.debian.org/debian-project/2019/12/msg00069.html
+
+People denying other people their humanity, their very right to exist,
+is something Debian should not tolerate. I think Debian should exclude
+people who do that from the project. Likewise, people defending the
+right to deny others their humanity should equally unacceptable.
+
+De-humanizing rhetoric isn't the only reason Debian stopped being fun.
+Everything else seems irrelevant, though. If people don't want others
+to even exist, there's no point in discussing minor points like
+improving a consensus building culture, paying off at least a
+noticeable part of the technical debt Debian carries from the past
+quarter century, or smoothing away some of the worst sources of
+friction in the development process of the project.
+
+Stop the hatred. The good will follow.

Change: publish draft
diff --git a/posts/2019/12/13/date_formats_in_international_contexts.mdwn b/posts/2019/12/13/date_formats_in_international_contexts.mdwn
index 647bd97..bbe08ea 100644
--- a/posts/2019/12/13/date_formats_in_international_contexts.mdwn
+++ b/posts/2019/12/13/date_formats_in_international_contexts.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Date formats in international contexts"]]
 [[!meta date="2019-12-13 10:38"]]
-[[!tag draft]]
+[[!tag ]]
 
 [poll]: https://toot.liw.fi/@liw/103295475472501319
 

Publish log entry
diff --git a/posts/2019/12/13/date_formats_in_international_contexts.mdwn b/posts/2019/12/13/date_formats_in_international_contexts.mdwn
new file mode 100644
index 0000000..647bd97
--- /dev/null
+++ b/posts/2019/12/13/date_formats_in_international_contexts.mdwn
@@ -0,0 +1,35 @@
+[[!meta title="Date formats in international contexts"]]
+[[!meta date="2019-12-13 10:38"]]
+[[!tag draft]]
+
+[poll]: https://toot.liw.fi/@liw/103295475472501319
+
+I made a [poll][] on the fediverse yesterday.
+
+> In an international context (e.g., company that works around the
+> globe, or a free software project with participants from several
+> continents), what's the right date format?
+
+The options and results:
+
+* 80% &mdash; 2019-12-13
+* 11% &mdash; 19 December 2019
+* 9% &mdash; 13/12/2019
+* 0% &mdash; 12/13/2019
+
+The one with the name of the month is a different date than the
+others. That was a typo; mea culpa. Nobody commented on that, though,
+and I doubt it affected the results.
+
+Here's my commentary. It was a bit of a trick question. Sorry. The
+first two options are both unambiguous as to which part is day, month,
+and year. The last two are entirely ambiguous, and require contextual
+information to interpret correctly. Thus, even though the third option
+is closest to what I'm used to from my own culture, I think it's
+utterly unsuitable in an international context.
+
+My own preference is to express the month as a word, or abbreviation,
+but in many cases being all numeric is easier.
+
+The most important bit is to be clear and unambiguous. Sometimes that
+means getting used to an unfamiliar notation.

Fix: title (missing word)
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index c8ade6b..4c45eeb 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -1,4 +1,4 @@
-[[!meta title="Free software development doesn't have to awful"]]
+[[!meta title="Free software development doesn't have to be awful"]]
 [[!meta date="2019-11-03 09:43"]]
 [[!tag debian gnu rms software-freedom tolerance governance]]
 

Fix: add missing word
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index cd0caf6..c8ade6b 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -33,7 +33,7 @@ A few of the other people in Debian I don't want to be
 associated with in any way, any more.
 
 Debian has some vocal people who treat other people in ways that I
-don't want accept. I don't want to go into specifics, or names,
+don't want to accept. I don't want to go into specifics, or names,
 because that's not going help me move forward.
 
 This is of course not a new thing. Debian has had problems with people

Fix: typo
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index acd2ad6..cd0caf6 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -58,7 +58,7 @@ GNU project. A lot of people are religously defending RMS and
 attacking his detractors. I find this to be problematic.
 
 [LWN][] has an excellent article on the topic. RMS has been behaving
-in problematic ways for a long time. He's not been publicaly
+in problematic ways for a long time. He's not been publicly
 confronted about it before, at the scale he has been now.
 
 [LWN]: https://lwn.net/Articles/802985/

Fix: typo
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index 879e3fa..acd2ad6 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -108,7 +108,7 @@ What should we in the software freedom movement do about all this?
 I've come to a few conclusions so far, though my process to think
 about this is ongoing.
 
-* Most importantly, we need to stop be tolerant of intolerance and bad
+* Most importantly, we need to stop being tolerant of intolerance and bad
   behaviour. It's time for all project, groups, and organisations in
   the movement to have and enforce at least a minimal level of civil
   behaviour. We are a movement consisting of many communities, and

Fix: word order
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index 49a0a22..879e3fa 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -84,7 +84,7 @@ harmful behavour, and tolerance of it.
 Harmful behaviour comes in many forms. Some people, for example, say
 outright that they don't want women involved in free software
 development. Others attack gay, lesbian, trans, queer, black, old,
-young, Christian, Muslim, atheist, other any other group of people
+young, Christian, Muslim, atheist, any other other group of people
 identified by whatever attribute the attacker happens to dislike. Yet
 others are more subtle, not attacking directly, but not giving people
 in the group they dislike the same chance to participate, learn, grow,

Fix: typo
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index 201c062..49a0a22 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -23,7 +23,7 @@ tools, file formats, and workflows Debian uses are getting a little
 archaic, and generally sub-optimal. Even mundane, everyday tasks
 involved much more friction than they should. Another is that making
 any large changes in Debian is too much of an effort, these days,
-partly because inertial, partly because it involves so many people.
+partly because of inertia, partly because it involves so many people.
 
 All of that could have been tolerable, if not for the people. Some of
 the nicest, most competent people I know work on Debian. It has been a

Change: publish
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
index 35d1631..201c062 100644
--- a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Free software development doesn't have to awful"]]
 [[!meta date="2019-11-03 09:43"]]
-[[!tag draft debian gnu rms software-freedom tolerance governance]]
+[[!tag debian gnu rms software-freedom tolerance governance]]
 
 I want to develop free software with people who lift up each other,
 and aren't arseholes.
@@ -156,3 +156,7 @@ is tolerated. I'm hoping this will have at least some effect.
 
 What about you?
 
+(My blog does not have comments, but you can respond to this 
+[fediverse][] thread: <https://toot.liw.fi/@liw/103080486083100970>.)
+
+[fediverse]: https://en.wikipedia.org/wiki/Fediverse

creating tag page tag/rms
diff --git a/tag/rms.mdwn b/tag/rms.mdwn
new file mode 100644
index 0000000..7063056
--- /dev/null
+++ b/tag/rms.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged rms"]]
+
+[[!inline pages="tagged(rms)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/gnu
diff --git a/tag/gnu.mdwn b/tag/gnu.mdwn
new file mode 100644
index 0000000..f17bb76
--- /dev/null
+++ b/tag/gnu.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged gnu"]]
+
+[[!inline pages="tagged(gnu)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/governance
diff --git a/tag/governance.mdwn b/tag/governance.mdwn
new file mode 100644
index 0000000..6e11bd5
--- /dev/null
+++ b/tag/governance.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged governance"]]
+
+[[!inline pages="tagged(governance)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/tolerance
diff --git a/tag/tolerance.mdwn b/tag/tolerance.mdwn
new file mode 100644
index 0000000..05386b4
--- /dev/null
+++ b/tag/tolerance.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged tolerance"]]
+
+[[!inline pages="tagged(tolerance)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
new file mode 100644
index 0000000..35d1631
--- /dev/null
+++ b/posts/2019/11/03/free_software_development_doesn_t_have_to_awful.mdwn
@@ -0,0 +1,158 @@
+[[!meta title="Free software development doesn't have to awful"]]
+[[!meta date="2019-11-03 09:43"]]
+[[!tag draft debian gnu rms software-freedom tolerance governance]]
+
+I want to develop free software with people who lift up each other,
+and aren't arseholes.
+
+A year ago I left Debian. The process is called retiring in Debian,
+and it's not final: if you do it in an orderly manner, you can come
+back again, and be re-instated as a Debian developer with a faster,
+more lightweight process than is used for entirely new developers.
+This was the third time I retired. The reasons were different than
+previously.
+
+The first two times I retired because I was pursuing other passions,
+and did not feel I could give Debian even the minimal attention and
+effort required to keep a few minor, leaf packages maintained. This
+time, I retired because Debian was not fun; it was in fact becoming
+awful, and I didn't want to participate anymore.
+
+Debian had stopped being fun for me in several ways. One was that the
+tools, file formats, and workflows Debian uses are getting a little
+archaic, and generally sub-optimal. Even mundane, everyday tasks
+involved much more friction than they should. Another is that making
+any large changes in Debian is too much of an effort, these days,
+partly because inertial, partly because it involves so many people.
+
+All of that could have been tolerable, if not for the people. Some of
+the nicest, most competent people I know work on Debian. It has been a
+privilege and a joy to work with them. 
+
+A few of the other people in Debian I don't want to be
+associated with in any way, any more.
+
+Debian has some vocal people who treat other people in ways that I
+don't want accept. I don't want to go into specifics, or names,
+because that's not going help me move forward.
+
+This is of course not a new thing. Debian has had problems with people
+behaving badly for years. I may have contributed to that, passively if
+not actively. However, as I get older, the friction from dealing with
+abrasive people is sanding off what thick skin I may have had when
+younger.
+
+As I get older, I am also learning that some of the things I thought
+were OK when I was younger, are in fact harmful to other people. I
+don't want to harm other people, and I don't want to participate in a
+project where some of the people insist on what I think is harmful
+behaviour, because they feel it's their right.
+
+Long after I left Debian, RMS managed to collapse the reality
+distortion field that's been surrounding and protecting him for many
+years. The triggering event for this was comments he made in a context
+involving Jeffrey Epstein. The comments caused a public uproar, and as
+a result RMS resigned from role of president of the Free Software
+Foundation, which he founded. He is currently still the leader of the
+GNU project. A lot of people are religously defending RMS and
+attacking his detractors. I find this to be problematic.
+
+[LWN][] has an excellent article on the topic. RMS has been behaving
+in problematic ways for a long time. He's not been publicaly
+confronted about it before, at the scale he has been now.
+
+[LWN]: https://lwn.net/Articles/802985/
+
+RMS has done some awesome things that he should be honoured for. He
+started the GNU project and gave it, and the world, a vision of being
+able to use computers whose entire software stack is free, and
+inventing copyleft, a legal tool to protect software freedom, as well
+as writing large amounts of the initial code in the GNU project. He
+has worked hard and long to help drive the vision of freedom into
+reality. For this, he shall always be remembered and revered.
+
+That doesn't excuse bad behaviour, such as insisting on abortion
+jokes, making women feel unwelcome in the GNU project, or various
+other things. I'm not going to make a list of his shortcomings,
+because this isn't a critique of RMS specifically. The problem I want
+to discuss isn't RMS or his personal behaviour.
+
+The problem I do want to discuss is that almost everywhere in the
+free and open source development communities there's a lot of
+harmful behavour, and tolerance of it.
+
+Harmful behaviour comes in many forms. Some people, for example, say
+outright that they don't want women involved in free software
+development. Others attack gay, lesbian, trans, queer, black, old,
+young, Christian, Muslim, atheist, other any other group of people
+identified by whatever attribute the attacker happens to dislike. Yet
+others are more subtle, not attacking directly, but not giving people
+in the group they dislike the same chance to participate, learn, grow,
+and generally be the best person they can be in the context of free
+software development.
+
+This doesn't just harm the groups of people being targeted. It harms
+others, who see it happen, and think they might be targeted too,
+later, maybe for some other reason. It harms reaching the vision of
+software freedom, because it shoves large parts of humanity outside
+the software freedom movement, robbing the movement from many voices
+and much effort. This makes it harder to achieve the vision.
+
+Excluding people from the movement for irrelevant reasons also harms
+humanity in general. It propagates the hate, hurt, and harm that is
+emblematic of life and politics around the world. While the software
+freedom movement can't solve all of those problems, we can and should
+at least not make it worse.
+
+What should we in the software freedom movement do about all this?
+I've come to a few conclusions so far, though my process to think
+about this is ongoing.
+
+* Most importantly, we need to stop be tolerant of intolerance and bad
+  behaviour. It's time for all project, groups, and organisations in
+  the movement to have and enforce at least a minimal level of civil
+  behaviour. We are a movement consisting of many communities, and
+  each community may want or need their own norms, and that's OK. Some
+  norms may even be in conflict. That's also OK, if unfortunate. 
+
+  Some people react to this kind of suggestion with hyperbolic claims
+  and conspiracy theories. I don't want to debate them. It's possible
+  to discuss community norms in a civil and constructive way. I know
+  this, because I've seen it happen many times. However, it requires
+  all participants to at least agree that there's behaviour that's
+  unwelcome, and not reject the notion of community norms outright.
+
+* I am by nature averse to conflicts. I will try to confront bad
+  behaviour in the future, rather than slinking away and going
+  elsewhere. I will at least speak out and say I think something is
+  unacceptable, when I see it.
+
+* I think the era for dictatorial models of governance for large free
+  software projects is over. For small projects, it's unavoidable,
+  because there's only one person doing any development, but when a
+  project grows, it doesn't work to have one person, or a small
+  anointed group, making all decisions. It's time to have more
+  democratic governance.
+
+  There are technical decisions that probably can't be done well by
+  letting everyone vote on them. However, every substantial project
+  will have other decisions that the whole community around the
+  project should have a say in. Voting on how to fix a bug may not be
+  workable, but voting on the minimum criteria for determining if a
+  bug fix is acceptable is. Should the project require adding a
+  regression test for any bug found in production? Should any such
+  test and bug fix be subjected to code review? Should such bugs and
+  their fixes be documented, even announced, publicly or kept secret?
+  How should security problems be handled?
+
+  In Debian, one of the guiding principles is that those who do,
+  decide. It seems time to involve those who use in the decision
+  making process as well.
+
+I can't force all communities in the software freedom movement to
+agree with me. Obviously not. I won't even try. I will, however, in
+the future be wary of joining dictatorial projects where bad behaviour
+is tolerated. I'm hoping this will have at least some effect.
+
+What about you?
+

Fix:typo
Thanks: Edward
diff --git a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
index 57c52d1..e127123 100644
--- a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
+++ b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
@@ -38,5 +38,5 @@ process, and ideally recorded as automated test cases.
 Code coverage is most useful when the main user of a piece of code is
 a developer, usually the developer who writes or maintains the code.
 In this case, coverage helps ensure all interesting parts of the code
-are unit tested. The unit tests capture the use cvases and acceptance
+are unit tested. The unit tests capture the use cases and acceptance
 criteria, in very fine-grained details.

Change: publish
diff --git a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
index cbae2c4..57c52d1 100644
--- a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
+++ b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Code coverage is almost pointless for tests"]]
 [[!meta date="2019-10-12 16:20"]]
-[[!tag draft automated-testing coverage use-case acceptance-criteria]]
+[[!tag automated-testing coverage use-case acceptance-criteria]]
 
 Measuring test coverage by measuring which parts of the code
 are executed tests is not useless, but it usually misses the point.

Change: tighten and clarify wording
diff --git a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
index 9ce4dcd..cbae2c4 100644
--- a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
+++ b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
@@ -2,10 +2,8 @@
 [[!meta date="2019-10-12 16:20"]]
 [[!tag draft automated-testing coverage use-case acceptance-criteria]]
 
-Measuring test coverage by using a tool to see what parts of the code
+Measuring test coverage by measuring which parts of the code
 are executed tests is not useless, but it usually misses the point.
-Expressing coverage as a percent of all lines of code is almost
-entirely pointless.
 
 [rant]: https://blog.liw.fi/posts/2019/06/29/dijkstra_was_only_partially_correct_about_testing/
 
@@ -13,24 +11,29 @@ Tests are not meant to show the absence of bugs, but to show what
 aspects of a program or system work. (See my previous [rant][].) If
 your automated tests execute 90% of your code lines, is that good
 enough? It doesn't really tell you what is tested and, crucially, what
-isn't. Users don't care about code lines. Users care about features
-and functionality. In other words, they care about use cases, or more
-specifically, they care about use cases that are acceptance criteria.
+isn't. Those using the software don't care about code lines. They care
+about being able to do the things they want to do. In other words,
+they care about use cases and acceptance criteria.
 
 The 10% of code not covered by your tests? If users never exercise
-them, they're dead code, and should probably be deleted. If those
+that code, it's dead code, and should probably be removed. If those
 lines keep crashing the program, producing wrong results, causing data
 loss, security problems, privacy leaks, or otherwise cause
-dissatisfaction for users, then that's a problem. How do you know?
+dissatisfaction, then that's a problem. How do you know?
 
-Test coverage should be measured of use cases and acceptance criteria.
+Test coverage should be measuring use cases and acceptance criteria.
 These are often not explicit, or written down, or even known. In most
-projects there are a lot of acceptance criteria and use cases, that
+projects there are a lot of acceptance criteria and use cases that
 are implicit, and only become explicit, when things don't work the way
 users want them to.
 
-A practical test coverage would be how many of the explicit, known,
-recorded use cases are tested?
+A realistic test coverage would be how many of the explicit, known,
+recorded use cases and acceptance criteria are tested by automated
+tests.
+
+Use cases are not always acceptance criteria. Acceptance criteria are
+not always use cases. Both need to be captured during the development
+process, and ideally recorded as automated test cases.
 
 Code coverage is most useful when the main user of a piece of code is
 a developer, usually the developer who writes or maintains the code.

creating tag page tag/use-case
diff --git a/tag/use-case.mdwn b/tag/use-case.mdwn
new file mode 100644
index 0000000..dc7e953
--- /dev/null
+++ b/tag/use-case.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged use-case"]]
+
+[[!inline pages="tagged(use-case)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/acceptance-criteria
diff --git a/tag/acceptance-criteria.mdwn b/tag/acceptance-criteria.mdwn
new file mode 100644
index 0000000..632978f
--- /dev/null
+++ b/tag/acceptance-criteria.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged acceptance-criteria"]]
+
+[[!inline pages="tagged(acceptance-criteria)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tag/automated-testing
diff --git a/tag/automated-testing.mdwn b/tag/automated-testing.mdwn
new file mode 100644
index 0000000..3eb05db
--- /dev/null
+++ b/tag/automated-testing.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged automated-testing"]]
+
+[[!inline pages="tagged(automated-testing)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
new file mode 100644
index 0000000..9ce4dcd
--- /dev/null
+++ b/posts/2019/10/12/code_coverage_is_almost_pointless_for_tests.mdwn
@@ -0,0 +1,39 @@
+[[!meta title="Code coverage is almost pointless for tests"]]
+[[!meta date="2019-10-12 16:20"]]
+[[!tag draft automated-testing coverage use-case acceptance-criteria]]
+
+Measuring test coverage by using a tool to see what parts of the code
+are executed tests is not useless, but it usually misses the point.
+Expressing coverage as a percent of all lines of code is almost
+entirely pointless.
+
+[rant]: https://blog.liw.fi/posts/2019/06/29/dijkstra_was_only_partially_correct_about_testing/
+
+Tests are not meant to show the absence of bugs, but to show what
+aspects of a program or system work. (See my previous [rant][].) If
+your automated tests execute 90% of your code lines, is that good
+enough? It doesn't really tell you what is tested and, crucially, what
+isn't. Users don't care about code lines. Users care about features
+and functionality. In other words, they care about use cases, or more
+specifically, they care about use cases that are acceptance criteria.
+
+The 10% of code not covered by your tests? If users never exercise
+them, they're dead code, and should probably be deleted. If those
+lines keep crashing the program, producing wrong results, causing data
+loss, security problems, privacy leaks, or otherwise cause
+dissatisfaction for users, then that's a problem. How do you know?
+
+Test coverage should be measured of use cases and acceptance criteria.
+These are often not explicit, or written down, or even known. In most
+projects there are a lot of acceptance criteria and use cases, that
+are implicit, and only become explicit, when things don't work the way
+users want them to.
+
+A practical test coverage would be how many of the explicit, known,
+recorded use cases are tested?
+
+Code coverage is most useful when the main user of a piece of code is
+a developer, usually the developer who writes or maintains the code.
+In this case, coverage helps ensure all interesting parts of the code
+are unit tested. The unit tests capture the use cvases and acceptance
+criteria, in very fine-grained details.

Fix: word form
diff --git a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
index eaabcb8..fc2eb9e 100644
--- a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
+++ b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
@@ -59,7 +59,7 @@ Good stuff:
   Arduino with a fancy peripheral.
 * Keyboard layout can be configured with the Chrysalis desktop software,
   without having to build and update a whole new firmware blob. I've
-  used to convert what is normall num lock to be scroll lock, so I can
+  used to convert what is normally num lock to be scroll lock, so I can
   use it as a compose key.
 
 I don't really have complaints, but of course one can always whinge:

Change: publish
diff --git a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
index 5b65f28..eaabcb8 100644
--- a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
+++ b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
@@ -1,6 +1,6 @@
 [[!meta title="Review: Keyboardio Model 01 keyboard"]]
 [[!meta date="2019-10-05 21:43"]]
-[[!tag draft review keyboardio]]
+[[!tag review keyboardio]]
 
 Some irrelevant personal history follows, skip to the next heading if
 uninterested. I first learnt to touch type on a portable, mechanical

Fix: plural
diff --git a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
index fdaffd0..5b65f28 100644
--- a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
+++ b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
@@ -83,4 +83,4 @@ offered to gift me a keyboard, they made no condition or request or
 even hint that I should write a review. They only asked that if I
 didn't like it, I'd gift it forward to some young hacker who would put
 it into good use, but couldn't afford it themselves. Sorry, young
-hacker, I'm keeping it.
+hackers, I'm keeping it.

Fix: word form
diff --git a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
index 7606458..fdaffd0 100644
--- a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
+++ b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
@@ -80,7 +80,7 @@ If necessary, I'd write another book to get one.
 
 Disclaimer: this review was not commissioned by Keyboardio. When they
 offered to gift me a keyboard, they made no condition or request or
-even hinted that I should write a review. They only asked that if I
+even hint that I should write a review. They only asked that if I
 didn't like it, I'd gift it forward to some young hacker who would put
 it into good use, but couldn't afford it themselves. Sorry, young
 hacker, I'm keeping it.

Fix: add missing word
diff --git a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
index 41726d1..7606458 100644
--- a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
+++ b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
@@ -2,7 +2,7 @@
 [[!meta date="2019-10-05 21:43"]]
 [[!tag draft review keyboardio]]
 
-Some irrelevant personal history follows, skip to next heading if
+Some irrelevant personal history follows, skip to the next heading if
 uninterested. I first learnt to touch type on a portable, mechanical
 typewriter in my early teens. It was a somewhat painful process: when
 I hit a key a little wrong, my finger would plunge between the keys

creating tag page tag/keyboardio
diff --git a/tag/keyboardio.mdwn b/tag/keyboardio.mdwn
new file mode 100644
index 0000000..d770e03
--- /dev/null
+++ b/tag/keyboardio.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged keyboardio"]]
+
+[[!inline pages="tagged(keyboardio)" actions="no" archive="yes"
+feedshow=10]]

Publish log entry
diff --git a/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
new file mode 100644
index 0000000..41726d1
--- /dev/null
+++ b/posts/2019/10/05/review_keyboardio_model_01_keyboard.mdwn
@@ -0,0 +1,86 @@
+[[!meta title="Review: Keyboardio Model 01 keyboard"]]
+[[!meta date="2019-10-05 21:43"]]
+[[!tag draft review keyboardio]]
+
+Some irrelevant personal history follows, skip to next heading if
+uninterested. I first learnt to touch type on a portable, mechanical
+typewriter in my early teens. It was a somewhat painful process: when
+I hit a key a little wrong, my finger would plunge between the keys
+into the internals of the typewriter, which was full of sharpish metal
+edges. I lost some blood to gain typing skills.
+
+Typing on computers is a joy in comparison. However, there's big
+differences between different keyboards. Over the decades I've learnt to
+prefer some types over others. Overall, my preference is for keyboards
+with mechanical switches over more rubbery ones. I type better and
+faster and more accurately when my fingers can sense that a key has been
+pressed.
+
+For some time I'd been using gaming PC keyboards with Cherry MX red
+switches. These are a joy to type on, but are quite noisy. I've also
+been curious about split keyboards. Earlier this year I heard of the
+[Keyboardio Model01](https://shop.keyboard.io/) keyboard, which started
+as a crowdfunded project. I was curious.
+
+However, it's expensive, for me, and quite different from anything I'd
+ever used before, so I was hesitant to get one. Luckily, I was
+introduced online to one of the founders of Keyboardio, who said they'd
+enjoyed the book I wrote for the Linux Documentation Project in the 90s,
+and would like to donate a keyboard for me. Joy!
+
+# Review
+
+I've been using the keyboard for some weeks now. Initially, I only used
+it to learn to touch type all over again. Not only is the keyboard
+different from any I'd been using before, but it seemed better suited to
+the US qwerty layout than the Finnish one, so I've been learning both a
+new physical layout and a logical layout.
+
+Also, I've been curious of using a US layout for programming for some
+time, and this is the perfect excuse to learn. Much fun. Luckily, it's
+not been actually painful, and I've not lost any blood this time.
+
+Now that I'm getting a little closer to my previous typing speed of 60
+words per minute on the new keyboard, it is time to write this review.
+I've never been a fast typist, but this speed seems to be fast enough
+that my brain doesn't get bored or frustrated waiting for my fingers
+to do their thing.
+
+Good stuff:
+
+* It just works. Plug it in via USB, and start typing.
+* Typing feel is great. It's fairly quiet, thanks to using Matias Quiet
+  Click key switches, instead of Cherry ones. Yet there's no doubt
+  about having pressed a key.
+* Build quality is good. Feels solid. They call it heirloom-grade,
+  and I can imagine this one lasting me decades.
+* The firmware is free software, hackable, and changing it does not void
+  warranty. I've not managed to brick the device. It's basically an
+  Arduino with a fancy peripheral.
+* Keyboard layout can be configured with the Chrysalis desktop software,
+  without having to build and update a whole new firmware blob. I've
+  used to convert what is normall num lock to be scroll lock, so I can
+  use it as a compose key.
+
+I don't really have complaints, but of course one can always whinge:
+
+* The Keyboardio website is a little disorganised and could be improved.
+  There might be a need for a documentation project just for this
+  keyboard and its firmware and associated software.
+* Oh boy does it take time and effort to learn to type all over again.
+  Even if it's worth it, it's still frustrating to re-learn something
+  I first learnt almost forty years ago.
+* I wasn't overly impressed with the bundled cables (USB-C and
+  Ethernet), but they're easy enough to replace. I now have cables
+  that are just the right length, even if it seems silly to use CAT7
+  to connect two halves of a keyboard.
+
+Verdict: I like the keyboard. If I lost it, I'd want to buy a new one.
+If necessary, I'd write another book to get one.
+
+Disclaimer: this review was not commissioned by Keyboardio. When they
+offered to gift me a keyboard, they made no condition or request or
+even hinted that I should write a review. They only asked that if I
+didn't like it, I'd gift it forward to some young hacker who would put
+it into good use, but couldn't afford it themselves. Sorry, young
+hacker, I'm keeping it.

Change: publish
diff --git a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
index a8d894d..b21d311 100644
--- a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
+++ b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="The reMarkable tablet: a review"]]
-[[!tag draft review remarkable]]
+[[!tag review remarkable]]
 [[!meta date="2019-09-22 10:00"]]
 
 [reMarkable]: https://remarkable.com/

Add: more emphasis
diff --git a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
index 857161a..a8d894d 100644
--- a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
+++ b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
@@ -73,7 +73,7 @@ considering to buy one.
   support would result in more hardware sold.
 
 * The way it renders PDF tables of content is ugly, hard to read, a
-  little slow, and a little easy to misnavigate.
+  little slow, and a little too easy to misnavigate.
 
 * The tablet does not follow intra-document links in PDFs. In some
   books this is annoying.

Fix: q to a
diff --git a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
index 88ef0ca..857161a 100644
--- a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
+++ b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
@@ -79,7 +79,7 @@ considering to buy one.
   books this is annoying.
 
 * There's a bug in the firmware when exporting annotations you've made
-  to q PDF with different sized pages. It turns out a lot of the books
+  to a PDF with different sized pages. It turns out a lot of the books
   I've bought as PDF have a cover page that's of a different size to
   the interior pages, and the tablet exports annotations relative to
   the top left of the cover page, rather than the page where the

Change: clarify free
diff --git a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
index 5321521..88ef0ca 100644
--- a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
+++ b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
@@ -62,7 +62,9 @@ considering to buy one.
   sure why it doesn't cache more, since I have gigabytes of free
   space.
 
-* The software isn't free, and the APIs, file formats, and data
+[free]: https://www.debian.org/social_contract#guidelines
+
+* The software isn't [free][], and the APIs, file formats, and data
   structures are not documented. This makes it harder to, say, sync
   any new documents to the device automatically. I bet the company
   would get an enthusiastic developer community in no time, if they

Add: ToC is hard to read
diff --git a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
index 705c4a4..5321521 100644
--- a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
+++ b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
@@ -70,8 +70,8 @@ considering to buy one.
   given they make their money from hardware sales and better software
   support would result in more hardware sold.
 
-* The way it renders PDF tables of content is ugly, a little slow, and
-  a little easy to misnavigate.
+* The way it renders PDF tables of content is ugly, hard to read, a
+  little slow, and a little easy to misnavigate.
 
 * The tablet does not follow intra-document links in PDFs. In some
   books this is annoying.

Fix: add missing word
diff --git a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
index f786980..705c4a4 100644
--- a/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
+++ b/posts/2019/09/22/the_remarkable_tablet_a_review.mdwn
@@ -4,7 +4,7 @@
 
 [reMarkable]: https://remarkable.com/
 
-The [reMarkable][] tablet is a 10" e-paper tablet on which you can PDF
+The [reMarkable][] tablet is a 10" e-paper tablet on which you can read PDF
 and ePub files, and write on with the stylus that comes with the
 device. It has fundamentally changed how I read textbooks.