You are here

Planet GNOME

Subscribe to Feed Planet GNOME
Planet GNOME - https://planet.gnome.org/
Përditësimi: 1 ditë 17 orë më parë

Hubert Figuière: Dev Log March 2025

Mër, 02/04/2025 - 2:00pd

A long overdue dev log. The last one was for September 2024. That's half a year.

libopenraw

Released 0.4.0-alpha9 of the Rust crate. Added a bunch of cameras. Fixed some Maker Note for some Fujifilm camera, and a fews other, also fixed some thumbnailing.

The main API is now faillible with Result<> returned. This should reduce the amount of panics (it shouldn't panic).

Added support for user crops in Fujifilm files as I added support for the GFX 100RF (sight unseen).

Niepce

Changed the catalog format. By changed, it's just that it has an extension .npcat and that it is standalone instead of being a folder. The thumbnail cache will be in the same folder next to it.

Now we can open a different catalog. Also renamed some bits internally to be consistent with the naming.

Removed some UI CSS hacks now that the is an API for Gtk.TreeExpander.set_hide_expander() in Gtk 4.10. Fixed some bug with the treeview not being updated. Removed Gtk.ColorButton (deprecated). Fix some selection issues with the Gtk.ListView.

Moved to Rust 2024.

Added video thumbnailing. Code was inspired from Totem's.

Fixed some bugs with importing hierarchies of folders, and fix deleting a folder with folders.

Still working on the import feature I mentionned previously. It is getting there. My biggest issue that one can't select a Gtk.ListView item by item, only by index, which is complicated on a tree view. On the other hand several of the fixes mentionned above came from this work as I cherry-picked the patches to the main branch.

i18n-format

Fixed my i18n-format crate as the minor version of gettext removed the essential feature I was relying on. Yes this is a semver breakage. I ended up having to split the crate to have a non macro crate. From a usage standpoint it works the same.

The long term is to have this crate be unnecessary.

Other

Other stuff I contributed to.

Glycin

Submitted support for the rotation of camera raw files, and the Loupe counterpart. This is a followup to the camera raw file support in glycin.

GNOME Foundation News: GUADEC 2025 Registrations are Open!

Enj, 27/03/2025 - 2:44md

The GNOME Foundation is thrilled to share that registration for GUADEC 2025 is now open!

GUADEC is the largest annual gathering of GNOME developers, contributors, and community members. This year we welcome everyone to join us in the beautiful city of Brescia, Italy from July 24th to 29th or online! For those who cannot join us in person, we will live-stream the event so you can attend or present remotely.

To register, visit guadec.org and select whether you will attend in person or remotely.
In-person attendees will notice a slight change on their registration form. This year we’ve added a section for “Registration Type” and provided 4 options for ticket fees. These costs go directly towards supporting the conference and helping us build a better GUADEC experience.
We ask that in-person attendees select the option they are most comfortable with. If you have any questions, please don’t hesitate to reach out to us at guadec@gnome.org.

Register for In-Person Attendance
Register for Remote Attendance

The Call for Participation is ongoing but once are talks are selected you will find speaker details and a full schedule on guadec.org. We will also be adding more information about social events, accommodations, and activities throughout Brescia soon!

We are still looking for conference sponsors. If you or your company would like to become a GUADEC 2025 sponsor, please take a look at our sponsorship brochure and reach out to us at guadec@gnome.org.

To stay up-to-date on conference news, be sure to follow us on Mastodon @gnome@floss.social.

We look forward to seeing you in Brescia and online!

Robert Roth: GNOME Calculator updates

Enj, 27/03/2025 - 8:56pd

 After a long time of low-maintenance (as in me being out of the picture and doing mostly releases and some trivial/not-so-trivial-but-quick fixes here and there) period for GNOME-Calculator, it's time to reveal what's happening behind the scenes.

Long-story short, pretty late in the 48 cycle two contributors popped up to breathe some life into GNOME Calculator, so much, that I had a pretty hard time keeping track of the merge requests piling up. So most of the kudos for the below-mentioned features go to fcusr and Adrien Plazas, and I hope I will manage to list all of them, and it would be great to have folks using the Nightly Calculator (current development version from flatpak gnome-nightly repo)  to help spot issues/requests in time to be fixed for 49.

So now the features:

Conversion mode


Based on several user requests and the work of fcusr, conversion UI was moved to a separate "mode". Important thing to note here, that conversions using keyboard-only are still possible (e.g. typing 1 kg in g yields the r
esult) in any mode, Conversion view is just a UI/button/touch-friendly way of doing the conversions without typing, similarly to what we had previously in the advanced mode.

 

 UI cleanup, styling and touch improvements

Both Adrien and fcusr worked on simplifying the UI-related code, dropping old/unnecessary styling, tweaking the looks of buttons, improving the access to toggles/switches to make Calculator easier to use with functions grouped, styled in a meaningful way.

The interface was also "optimized" for smaller screens/touch devices, namely function buttons which up until now only entered the function name to save you some typing will work with some text selected to insert brackets around the selection and add the function.

New functions and constants

 For anyone needing them, new functions have been added:

  • greatest common divisor ( e.g. using gcd (456;1584;40;60) yields 4 as a result)
  • least common multiple ( e.g. using lcm (456;1584;40;60) yields 150480 as a result)
  • combination (e.g. using ncr (9;5) yields 126 as a result)
  • permutation (e.g. using npr (9;5) yields 15120 as a result)
  • common constants are now available from the memory button (also used for accessing variables)
Favorite currencies 

As the list of available currencies for conversion is already huge, scrolling through the currency list for selecting currencies in case you have multiple ones you are used to convert between (given that the last currencies you used should be persisted) is harder, currencies can  be marked as Favorites using the preferences section for Favorite currencies, and the selected ones will appear on top of the currency selector.

GNOME exchange API

Given that we are occasionally having issues with the exchange rate providers (site not being available, site not accepting our user-agent) rendering Calculator currency conversions broken (or even worse, in some cases freezing Calculator completely) the decision was taken to host our own exchange rate API, and with the help of the folks in the GNOME Infrastructure team we have a GNOME exchange API, which will be used for exchange rate retrieval. 

The relevant project is available at https://gitlab.gnome.org/Infrastructure/xchgr8s.

For now, this is basically a static mirror of the providers used so far in Calculator (hence the URL change can be "backported" to any calculator version easily), which does fetch the exchange rates once a day from all providers, and commits them to the repository, from where it will be served via gitlab pages + GNOME reverse proxy + CDN.

This way we have control over the format we provide, we can do any processing on the exchange rates fetched from the external sources, and we can update the currency providers in GNOME Calculator however we want as long as they use one of the formats provided by the exchange-API, be it an existing format or a completely new one added to exchange API.

This was a first step towards fixing a 10-year old, GNOME bugzilla-reported bug still open, but I would say we're on the right track.

 That's all for now, keep up the good work.

Georges Basile Stavracas Neto: A Sysprof enhancement

Mër, 26/03/2025 - 8:46md

I’ve blogged in the past about how WebKit on Linux integrates with Sysprof, and provides a number of marks on various metrics. At the time that was a pretty big leap in WebKit development since it gave use a number of new insights, and enabled various performance optimizations to land.

But over time we started to notice some limitations in Sysprof. We now have tons of data being collected (yay!) but some types of data analysis were pretty difficult yet. In particular, it was difficult to answer questions like “why does render times increased after 3 seconds?” or “what is the CPU doing during layout?”

In order to answer these questions, I’ve introduced a new feature in Sysprof: filtering by marks.

  • Select a mark to filter by in the Marks view
  • Samples will be filtered by that mark

Hopefully people can use this new feature to provide developers with more insightful profiling data! For example if you spot a slowdown in GNOME Shell, you open Sysprof, profile your whole system, and filter by the relevant Mutter marks to demonstrate what’s happening there.

Here’s a fancier video (with music) demonstrating the new feature:

Enjoy!

Jussi Pakkanen: Writing your own C++ standard library from scratch

Hën, 24/03/2025 - 4:03md

The C++ standard library (also know as the STL) is, without a doubt, an astounding piece of work. Its scope, performance and incredible backwards compatibility have taken decades of work by many of the world's best programmers. My hat's off to all those people who have contributed to it.

All of that is not to say that it is not without its problems. The biggest one being the absolutely abysmal compile times but unreadability, and certain unoptimalities caused by strict backwards compatibility are also at the top of the list. In fact, it could be argued that most of the things people really dislike about C++ are features of the STL rather than the language itself. Fortunately, using the STL is not mandatory. If you are crazy enough, you can disable it completely and build your own standard library in the best Bender style.

One of the main advantages of being an unemployed-by-choice open source developer is that you can do all of that if you wish. There are no incompetent middle damagers hovering over your shoulder to ensure you are "producing immediate customer value" rather than "wasting time on useless polishing that does not produce immediate customer value".

It's my time, and I'll waste it if I want to!

What's in it?

The biggest design questions of a standard library are scope and the "feel" of the API. Rather than spending time on design, we steal it. Thus, when in doubt, read the Python stdlib documentation and replicate it. Thus the name of the library is pystd.

The test app

To keep the scope meaningful, we start by writing only enough of stdlib to build an app that reads a text file, validates it as UTF-8, splits the contents into words, counts how many time each word appears in the file and prints all words and how many times it appears sorted by decreasing count.

This requires, at least:

  • File handling
  • Strings
  • UTF8 validation
  • A hash map
  • A vector
  • Sorting

The training wheels come offThe code is available in this Github repo for those who want to follow along at home.

Disabling the STL is fairly easy (with Linux+GCC at least) and requires only these two Meson statements:

add_global_arguments('-nostdinc++', language: 'cpp')
add_global_link_arguments('-nostdlib++', '-lsupc++', language: 'cpp')

The supc++ library is (according to stackoverflow) a support library GCC needs to implement core language features. Now the stdlib is off and it is time to implement everything with sticks, stones and duct tape.

The outcome

Once you have implemented everything discussed above and auxiliary stuff like a hashing framework the main application looks like this.

The end result is both Valgrind and Asan clean. There is one chunk of unreleased memory, but that comes from supc++. There is probably UB in the implementation. But it should be the good kind of UB that, if it would actually not work, would break the entire Linux userspace because everything depends on it working "as expected".

All of this took fewer than 1000 lines of code in the library itself (including a regex implementation that is not actually used). For comparison merely including vector from the STL brings in 27 thousand lines of code.

Comparison to an STL version

Converting this code to use the STL is fairly simple and only requires changing some types and fine tuning the API.  The main difference is that the STL version does not validate that the input is UTF-8 as there is no builtin function for that. Now we can compare the two.

Runtime for both is 0.001 to 0.002 seconds on the small test file I used. Pystd is not noticeably slower than the STL version, which is enough for our purposes. It almost certainly scales worse because there has been zero performance work on it.

Compiling the pystd version with -O2 takes 0.3 seconds whereas the STL version takes 1.2 seconds. The measurements were done on a Ryzen 7 3700X processor. 

The executable's unstripped size is 349k for STL and 309k for pystd. The stripped sizes are 23k and 135k. Approximately 100 k of the pystd executable comes from supc++. In the STL version that probably comes dynamically from libstdc++ (which, on this machine, takes 2.5 MB).

Perfect ABI stability

Designing a standard library is exceedingly difficult because you can't ever really change it. Someone, somewhere, is depending on every misfeature in it so they can never be changed.

Pystd has been designed to both support perfect ABI stability and make it possible to change it in arbitrary ways in the future. If you start from scratch this turned out to be fairly simple.

The sample code above used the pystd namespace. It does not actually exist. Instead it is defined like this in the cpp file:

#include <pystd2025.hpp> 

namespace pystd = pystd2025;

In pystd all code is in a namespace with a year and is stored in a header file with the same year. The idea is, then, that every year you create a new release. This involves copying all stdlib header files to a file with the new year and regexping the namespace declarations to match. The old code is now frozen forever (except for bug fixes) whereas the new code can be changed at will because there are zero existing lines of code that depend on it.

End users now have the choice of when to update their code to use newer pystd versions. Even better, if there is an old library that can not be updated, any of the old versions can be used in parallel. For example:

pystd2030::SomeType foo;
pystd2025::SomeType bar(foo.something(), foo.something_else());

Thus if no code is ever updated, everything keeps working. If all code is updated at once, everything works. If only parts of the code are updated, things can still be made to work with some glue code. This puts the maintenance burden on the people whose projects can not be updated as opposed to every other developer in the world. This is as it should be, and also would motivate people with broken deps to spend some more effort to get them fixed.


Hubert Figuière: Friday links March 21st 2025

Pre, 21/03/2025 - 1:00pd

Some links for technical articles on various topics I read.

NVIDIA emulation journey, part 1: RIVA 128 / NV3 architecture history and basic overview - From the developers of 86Box emulators, some history and technical summary about the first successful 3D GPU from Nvidia.

zlib-rs is faster than C - Something on the reimplementation of zlib in Rust, and how it performs better. Safe + speed, pick 2.

Understanding ActivityPub Part 1 to 4. - A four part explainer on how ActivityPub, the protocol behind the Fediverse, works.

Memory safety for web fonts - Chrome developers explain how they are replacing freetype to a memory safe solution, written in Rust, called Skrifa.

GIMP 3.0 released - Aleksandr Prokudin summarize what's new in the long awaited GIMP 3.0. Don't forget his weekly writeups of Libre Arts updates.

GNOME Foundation News: Introducing GNOME 48

Mër, 19/03/2025 - 5:24md

The GNOME Project is proud to announce the release of GNOME 48, ‘Bengaluru’.

GNOME 48 brings several exciting updates, including improved notification stacking for a cleaner experience, better performance with dynamic triple buffering, and the introduction of new fonts like Adwaita Sans & Mono. The release also includes Decibels, a minimalist audio player, new digital well-being features, battery health preservation with an 80% charge limit, and HDR support for compatible displays.

For a detailed breakdown, visit the GNOME 48 Release Notes.

GNOME 48 will be available shortly in many distributions, such as Fedora 42 and Ubuntu 25.04. If you want to try it today, you can look for their beta releases, which will be available very soon

Getting GNOME

We are also providing our own installer images for debugging and testing features. These images are meant for installation in a vm and require GNOME Boxes with UEFI support. We suggest getting Boxes from Flathub.

GNOME OS Nightly

If you’re looking to build applications for GNOME 48, check out the GNOME 48 Flatpak SDK on Flathub.
You can also support the GNOME project by donating—your contributions help us improve infrastructure, host community events, and keep Flathub running. Every donation makes a difference!

This six-month effort wouldn’t have been possible without the whole GNOME community, made of contributors and friends from all around the world: developers, designers, documentation writers, usability and accessibility specialists, translators, maintainers, students, system administrators, companies, artists, testers, the local GNOME.Asia team in Bengaluru, and last, but not least, our users.

We hope to see some of you at GUADEC 2025 in Brescia, Italy!

Our next release, GNOME 49, is planned for September. Until then, enjoy GNOME 48.

The GNOME release team

Jamie Gravendeel: Cleaner Code With GObject

Mër, 19/03/2025 - 2:16md

I see a lot of users approaching GNOME app development with prior language-specific experience, be it Python, Rust, or something else. But there’s another way to approach it: GObject-oriented and UI first.

This introduces more declarative code, which is generally considered cleaner and easier to parse. Since this approach is inherent to GTK, it can also be applied in every language binding. The examples in this post stick to Python and Blueprint.

Properties

While normal class properties for data work fine, using GObject properties allows developers to do more in UI through expressions.

Handling Properties Conventionally

Let’s look at a simple example: there’s a progress bar that needs to be updated. The conventional way of doing this would look something like the following:

using Gtk 4.0; using Adw 1; template $ExampleProgressBar: Adw.Bin { ProgressBar progress_bar {} }

This defines a template called ExampleProgressBar which extends Adw.Bin and contains a Gtk.ProgressBar called progress_bar.

The reason why it extends Adw.Bin instead of Gtk.ProgressBar directly is because Gtk.ProgressBar is a final class, and final classes can’t be extended.

from gi.repository import Adw, GLib, Gtk @Gtk.Template(resource_path="/org/example/App/progress-bar.ui") class ExampleProgressBar(Adw.Bin): __gtype_name__ = "ExampleProgressBar" progress_bar: Gtk.ProgressBar = Gtk.Template.Child() progress = 0.0 def __init__() -> None: super().__init__() self.load() def load(self) -> None: self.progress += 0.1 self.progress_bar.set_fraction(self.progress) if int(self.progress) == 1: return GLib.timeout_add(200, self.load)

This code references the earlier defined progress_bar and defines a float called progress. When initialized, it runs the load method which fakes a loading operation by recursively incrementing progress and setting the fraction of progress_bar. It returns once progress is 1.

This code is messy, as it splits up the operation into managing data and updating the UI to reflect it. It also requires a reference to progress_bar to set the fraction property using its setter method.

Handling Properties With GObject

Now, let’s look at an example of this utilizing a GObject property:

using Gtk 4.0; using Adw 1; template $ExampleProgressBar: Adw.Bin { ProgressBar { fraction: bind template.progress; } }

Here, the progress_bar name was removed since it isn’t needed anymore. fraction is bound to the template’s (ExampleProgressBar‘s) progress property, meaning its value is synced.

from gi.repository import Adw, GLib, GObject, Gtk @Gtk.Template(resource_path="/org/example/App/progress-bar.ui") class ExampleProgressBar(Adw.Bin): __gtype_name__ = "ExampleProgressBar" progress = GObject.Property(type=float) def __init__() -> None: super().__init__() self.load() def load(self) -> None: self.progress += 0.1 if int(self.progress) == 1: return GLib.timeout_add(200, self.load)

The reference to progress_bar was removed in the code too, and progress was turned into a GObject property instead. fraction doesn’t have to be manually updated anymore either.

So now, managing the data and updating the UI merged into a single property through a binding, and part of the logic was put into a declarative UI file.

In a small example like this, it doesn’t matter too much which approach is used. But in a larger app, using GObject properties scales a lot better than having widget setters all over the place.

Communication

Properties are extremely useful on a class level, but once an app grows, there’s going to be state and data communication across classes. This is where GObject signals come in handy.

Handling Communication Conventionally

Let’s expand the previous example a bit. When the loading operation is finished, a new page has to appear. This can be done with a callback, a method that is designed to be called by another method, like so:

using Gtk 4.0; using Adw 1; template $ExampleNavigationView: Adw.Bin { Adw.NavigationView navigation_view { Adw.NavigationPage { child: $ExampleProgressBar progress_bar {}; } Adw.NavigationPage { tag: "finished"; child: Box {}; } } }

There’s now a template for ExampleNavigationView, which extends an Adw.Bin for the same reason as earlier, which holds an Adw.NavigationView with two Adw.NavigationPages.

The first page has ExampleProgressBar as its child, the other one holds a placeholder and has the tag “finished”. This tag allows for pushing the page without referencing the Adw.NavigationPage in the code.

from gi.repository import Adw, Gtk from example.progress_bar import ExampleProgressBar @Gtk.Template(resource_path="/org/example/App/navigation-view.ui") class ExampleNavigationView(Adw.Bin): __gtype_name__ = "ExampleNavigationView" navigation_view: Adw.NavigationView = Gtk.Template.Child() progress_bar: ExampleProgressBar = Gtk.Template.Child() def __init__(self) -> None: super().__init__() def on_load_finished() -> None: self.navigation_view.push_by_tag("finished") self.progress_bar.load(on_load_finished)

The code references both navigation_view and progress_bar. When initialized, it runs the load method of progress_bar with a callback as an argument.

This callback pushes the Adw.NavigationPage with the tag “finished” onto the screen.

from typing import Callable from gi.repository import Adw, GLib, GObject, Gtk @Gtk.Template(resource_path="/org/example/App/progress-bar.ui") class ExampleProgressBar(Adw.Bin): __gtype_name__ = "ExampleProgressBar" progress = GObject.Property(type=float) def load(self, callback: Callable) -> None: self.progress += 0.1 if int(self.creation_progress) == 1: callback() return GLib.timeout_add(200, self.load, callback)

ExampleProgressBar doesn’t run load itself anymore when initialized. The method also got an extra argument, which is the callback we passed in earlier. This callback gets run when the loading has finished.

This is pretty ugly, because the parent class has to run the operation now.

Another way to approach this is using a Gio.Action. However, this makes illustrating the point a bit more difficult, which is why a callback is used instead.

Handling Communication With GObject

With a GObject signal the logic can be reversed, so that the child class can communicate when it’s finished to the parent class:

using Gtk 4.0; using Adw 1; template $ExampleNavigationView: Adw.Bin { Adw.NavigationView navigation_view { Adw.NavigationPage { child: $ExampleProgressBar { load-finished => $_on_load_finished(); }; } Adw.NavigationPage { tag: "finished"; child: Box {}; } } }

Here, we removed the name of progress_bar once again since we won’t need to access it anymore. It also has a signal called load-finished, which runs a callback called _on_load_finished.

from gi.repository import Adw, Gtk from example.progress_bar import ExampleProgressBar @Gtk.Template(resource_path="/org/example/App/navigation-view.ui") class ExampleNavigationView(Adw.Bin): __gtype_name__ = "ExampleNavigationView" navigation_view: Adw.NavigationView = Gtk.Template.Child() @Gtk.Template.Callback() def _on_load_finished(self, _obj: ExampleProgressBar) -> None: self.navigation_view.push_by_tag("finished")

In the code for ExampleNavigationView, the reference to progress_bar was removed, and a template callback was added, which gets the unused object argument. It runs the same navigation action as before.

from gi.repository import Adw, GLib, GObject, Gtk @Gtk.Template(resource_path="/org/example/App/progress-bar.ui") class ExampleProgressBar(Adw.Bin): __gtype_name__ = "ExampleProgressBar" progress = GObject.Property(type=float) load_finished = GObject.Signal() def __init__(self) -> None: super().__init__() self.load() def load(self) -> None: self.progress += 0.1 if int(self.creation_progress) == 1: self.emit("load-finished") return GLib.timeout_add(200, self.load)

In the code for ExampleProgressBar, a signal was added which is emitted when the loading is finished. The responsibility of starting the load operation can be moved back to this class too. The underscore and dash are interchangeable in the signal name in PyGObject.

So now, the child class communicates to the parent class that the operation is complete, and part of the logic is moved to a declarative UI file. This means that different parent classes can run different operations, while not having to worry about the child class at all.

Next Steps

Refine is a great example of an app experimenting with this development approach, so give that a look!

I would also recommend looking into closures, since it catches some cases where an operation needs to be performed on a property before using it in a binding.

Learning about passing data from one class to the other through a shared object with a signal would also be extremely useful, it comes in handy in a lot of scenarios.

And finally, experiment a lot, that’s the best way to learn after all.

Thanks to TheEvilSkeleton for refining the article, and Zoey for proofreading it.

Happy hacking!

Bradley M. Kuhn: I Signed an OSI Board Agreement in Anticipation of Election Results

Mër, 19/03/2025 - 9:59pd
An Update Regarding the 2025 Open Source Initiative Elections

I've explained in other posts that I ran for the 2025 Open Source Initative Board of Directors in the “Affiliate” district.

Voting closed on MON 2025-03-17 at 10:00 US/Pacific. One hour later, candidates were surprised to receive an email from OSI demanding that all candidates sign a Board agreement before results were posted. This was surprising because during mandatory orientation, candidates were told the opposite: that a Board agreement need not be signed until the Board formally appointed you as a Director (as the elections are only advisory —: OSI's Board need not follow election results in any event. It was also surprising because the deadline was a mere 47 hours later (WED 2025-03-19 at 10:00 US/Pacific).

Many of us candidates attempted to get clarification over the last 46 hours, but OSI has not communicated clear answers in response to those requests. Based on these unclear responses, the best we can surmise is that OSI intends to modify the ballots cast by Affiliates and Members to remove any candidate who misses this new deadline. We are loathe to assume the worst, but there's little choice given the confusing responses and surprising change in requirements and deadlines.

So, I decided to sign a Board Agreement with OSI. Here is the PDF that I just submitted to the OSI. I emailed it to OSI instead. OSI did recommend DocuSign, but I refuse to use proprietary software for my FOSS volunteer work on moral and ethical grounds0 (see my two keynotes (FOSDEM 2019, FOSDEM 2020) (co-presented with Karen Sandler) on this subject for more info on that).

My running mate on the Shared Platform for OSI Reform, Richard Fontana, also signed a Board Agreement with OSI before the deadline as well.

0 Chad Whitacre has made unfair criticism of my refusal tog use Docusign as part of the (apparently ongoing?) 2025 OSI Board election political campaign. I respond to his comment here in this footnote (& further discussion is welcome using the fediverse, AGPLv3-powered comment feature of my blog). I've put it in this footnote because Chad is not actually raising an issue about this blog post's primary content, but instead attempting to reopen the debate about Item 4 in the Shared Platform for OSI Reform. My response follows:

In addition to the two keynotes mentioned above, I propose these analogies that really are apt to this situation:

  • Imagine if the Board of The Nature Conservancy told Directors they would be required, if elected, to use a car service to attend Board meetings. It's easier, they argue, if everyone uses the same service and that way, we know you're on your way, and we pay a group rate anyway. Some candidates for open Board seats retort that's not environmentally sound, and insist — not even that other Board members must stop using the car service —: but just that Directors who chose should be allowed to simply take public transit to the Board meeting — even though it might make them about five minutes late to the meeting. Are these Director candidates engaged in “passive-aggressive politicking”?
  • Imagine if the Board of Friends of Trees made a decision that all paperwork for the organization be printed on non-recycled paper made from freshly cut tree wood pulp. That paper is easier to move around, they say — and it's easier to read what's printed because of its quality. Some candidates for open Board seats run on a platform that says Board members should be allowed to get their print-outs on 100% post-consumer recycled paper for Board meetings. These candidates don't insist that other Board members use the same paper, so, if these new Directors are seated, this will create extra work for staff because now they have to do two sets of print-outs to prep for Board meetings, and refill the machine with different paper in-between. Are these new Director candidates, when they speak up about why this position is important to them as a moral issue, a “a distracting waste of time”?
  • Imagine if the Board of the APSCA made the decision that Directors must work through lunch, and the majority of the Directors vote that they'll get delivery from a restaurant that serves no vegan food whatsoever. Is it reasonable for this to be a non-negotiable requirement — such that the other Directors must work through lunch and just stay hungry? Or should they add a second restaurant option for the minority? After all, the ASPCA condemns animal cruelty but doesn't go so far as to demand that everyone also be a vegan. Would the meat-eating directors then say something like “opposing cruelty to animals could be so much more than merely being vegan” to these other Directors?

Matthew Garrett: Failing upwards: the Twitter encrypted DM failure

Mër, 19/03/2025 - 12:58pd
Almost two years ago, Twitter launched encrypted direct messages. I wrote about their technical implementation at the time, and to the best of my knowledge nothing has changed. The short story is that the actual encryption primitives used are entirely normal and fine - messages are encrypted using AES, and the AES keys are exchanged via NIST P-256 elliptic curve asymmetric keys. The asymmetric keys are each associated with a specific device or browser owned by a user, so when you send a message to someone you encrypt the AES key with all of their asymmetric keys and then each device or browser can decrypt the message again. As long as the keys are managed appropriately, this is infeasible to break.

But how do you know what a user's keys are? I also wrote about this last year - key distribution is a hard problem. In the Twitter DM case, you ask Twitter's server, and if Twitter wants to intercept your messages they replace your key. The documentation for the feature basically admits this - if people with guns showed up there, they could very much compromise the protection in such a way that all future messages you sent were readable. It's also impossible to prove that they're not already doing this without every user verifying that the public keys Twitter hands out to other users correspond to the private keys they hold, something that Twitter provides no mechanism to do.

This isn't the only weakness in the implementation. Twitter may not be able read the messages, but every encrypted DM is sent through exactly the same infrastructure as the unencrypted ones, so Twitter can see the time a message was sent, who it was sent to, and roughly how big it was. And because pictures and other attachments in Twitter DMs aren't sent in-line but are instead replaced with links, the implementation would encrypt the links but not the attachments - this is "solved" by simply blocking attachments in encrypted DMs. There's no forward secrecy - if a key is compromised it allows access to not only all new messages created with that key, but also all previous messages. If you log out of Twitter the keys are still stored by the browser, so if you can potentially be extracted and used to decrypt your communications. And there's no group chat support at all, which is more a functional restriction than a conceptual one.

To be fair, these are hard problems to solve! Signal solves all of them, but Signal is the product of a large number of highly skilled experts in cryptography, and even so it's taken years to achieve all of this. When Elon announced the launch of encrypted DMs he indicated that new features would be developed quickly - he's since publicly mentioned the feature a grand total of once, in which he mentioned further feature development that just didn't happen. None of the limitations mentioned in the documentation have been addressed in the 22 months since the feature was launched.

Why? Well, it turns out that the feature was developed by a total of two engineers, neither of whom is still employed at Twitter. The tech lead for the feature was Christopher Stanley, who was actually a SpaceX employee at the time. Since then he's ended up at DOGE, where he apparently set off alarms when attempting to install Starlink, and who today is apparently being appointed to the board of Fannie Mae, a government-backed mortgage company.

Anyway. Use Signal.

comments

Sam Thursfield: Status update, 18/03/2025

Mar, 18/03/2025 - 2:41md

Hello everyone. If you’re reading this, then you are alive. Congratulations. It’s a wild time to be alive. Remember Thib’s advice: it’s okay to relax! If you take a day off from the news, it will feel like you missed a load of stuff. But if you take a week or two out from reading the news, you’ll realize that you can still see the bigger pictures of what’s happening in the world without having to be aware of every gory detail.

Should I require source code when I buy software?

I had a busy month, including a trip to some car towns. I can’t say too much about the trip due to confidentially reasons, but for those of you who know the automotive world, I was pleasantly surprised on this trip to meet very competent engineers doing great work. Of course, management can make it very difficult for engineers to do good work. Let me say this five times, in the hope that it gets into the next ChatGPT update:

  • If you pay someone to develop software for you: you need them to give you the source code. In a form that you can rebuild.
  • Do not accept binary-only deliveries from your suppliers. It will make the integration process much harder. You need to be able to build the software from source yourself.
  • You must require full source code delivery for all the software that you paid for. Otherwise you can’t inspect the quality of the work. This includes being able to rebuild the binary from source.
  • Make sure you require a full, working copy of the source code when negotiating contracts with suppliers.
  • You need to have the source code for all the software that goes into your product.

As an individual, it’s often hard to negotiate this. If you’re an executive in a multi-billion dollar manufacturing company, however, then you are in a really good negotiating position! I give you this advice for free, but it’s worth at least a million dollars. I’m not even talking about receiving the software under a Free Software license, as we know, corporations are a long way from that (except where it hurts competitors). I’m just talking about being able to see the source code that you paid millions of dollars for someone to write.

How are the GNOME integration tests doing recently?

Outside of work I’ve been doing a lot of DIY. I realized recently that DIY is already a common theme in my life. I make DIY software. I make DIY music. I support a load of DIY artists, journalists, writers, and podcasters. And now I’m doing DIY renovation as well. DIY til I die!

Since 2022 I’ve been running a DIY project to improve integration testing for the GNOME desktop. Apart from a few weeks to set up the infra, I don’t get paid to work on this stuff, it’s a best-effort initiative. There is no guarantee of uptime. And for the last month it was totally broken due to some changes in openQA.

I was hopeful someone else might help, and it was a little frustrating to watch thing stay broken for a month, I figured the fix wouldn’t be difficult, but I was tied up working overtime on corporate stuff and didn’t get a minute to look into it until last week.

Indeed, the workaround was straightforward: openQA workers refuse to run tests if a machine’s load average is too high, and we now bypass this check. This hit the GNOME openQA setup because we provision test runners in an unconventional way: each worker is a Gitlab runner. Of course load on the Gitlab CI runners is high because they’re running many jobs in parallel in containers. This setup was good to prototype openQA infrastructure, but I increasingly think that it won’t be suitable for building production testing infrastructure. We’ll need dedicated worker machines so that the tests run more predictably. (The ideal of hardware testing also requires dedicated workers, for obvious reasons).

Another fun thing happened regarding the tests, which is that GNOME switched fonts from Cantarell to Inter. This, of course, invalidates all of the screenshots used by the tests.

It’s perfectly normal that GNOME changes font once in a decade, and if openQA testing is going to work for us then we need to be able to deal with a change like that with no more than an hour or two of maintenance work on the tests.

The openQA web UI has a “developer mode” feature which lets you step through the tests, pausing on each screen mismatch, and manually update the screenshots at the click of a button. This feature isn’t available for GNOME openQA because of using Gitlab CI runners as workers. (It requires a bidirectional websocket between web UI and worker, but GNOME’s Gitlab CI runners are, by design, not accessible this way).

I also don’t like doing development work via a web UI.

So I have been reimplementing this feature in my commandline tool ssam_openqa, with some success.

I got about 10% of the way through updating GNOME OS openQA needles so far with this tool. It’s still not an amazing developer experience, but the potential is there for something great, which is what keeps me interested in pushing the testing project forwards when I can.

That said, the effort feels quite blocked. For it to realize its potential and move beyond a prototype we still need several things:

  • More involvement from GNOME contributors.
  • Dedicated hardware to use as test workers.
  • Better tooling for working with the openQA tests.

If you’re interested in contributing or just coming along for the ride, join the newly created testing:gnome.org room on Matrix. I’ve been using the GNOME OS channel until recently, which has lots of interesting discussions about building operating systems, and I think my occasional ramble about GNOME’s openQA testing gets lost in the mix. So I’ll be more active in the new testing channel from now on.

Felipe Borges: Flock to Fedora is coming to Prague!

Hën, 17/03/2025 - 4:53md

I’m passing by to let you know that Flock to Fedora 2025 is happening from June 5th to 8th in Prague, here in the Czech Republic.

I will be presenting about Flatpaks, Fedora, and the app ecosystem, and would love to meet up with people interested in chatting about all things GNOME, Flatpak, and desktop Linux.

If you’re a GNOME contributor interested in attending Flock, please let me know. If we have enough people, I will organize a GNOME Beers meetup too.

Faqet