Tag: 666a

Shutting down 666a

Since October 31st 2023 I've been providing a work environment email service called 666a. On March 31st 2025 it's shutting down. Today I'm beginning the process of winding it down gently, and I wanted to post something explaining that process and why it's happening.

Immediate Changes

The following are effective right now. They've already happened, in fact.

  1. The SendGrid account is downgraded to the free tier.
  2. Sign ups are disabled on 666a.se.
  3. The translated Swedish legislation has been migrated to lagstiftning.codeberg.page. This part I'm particularly pleased with. I actually think it will be easier to maintain this resource in the long term in this new form.

With these changes in place, what's left on 666a.se is the code for delivering the email alerting service. Existing users are welcome to update their contact details or even request a full account deletion if they wish to.

February 1st 2025

At the start of Feburary, the SendGrid downgrade will kick in. This probably won't have any major effect on the reliability of the service as we're in the relatively quiet early months of the year. But if there's a busy day in February or March, some email alerts are going to fail to send.

March 31st 2025

The idea is to keep the alerts running until the end of March so that you get pretty much an entire quarter of the year of notice before they stop coming. I've seen paid services close down and disappear faster than this and it feels sufficient. March 31st is the final day, and here's how it's going to go down.

  1. Delete the rolling database backups I keep on my home server's external USB.
  2. Run shutdown:anonymize on my only remaining copy of the data to clean out the personally identifiable information from it and make it privately archivable for myself.
  3. Scale down the Fly cluster to 0 instances and delete the storage volume. At this point the service will become unrecoverable.
  4. Point the domain name at a static host containing a short explanatory notice and 301 redirects for all the translated Swedish legislation URLs.

After that I'll probably leave the domain up to serve the redirects for a year or two. I think people mostly share links to employment law with each other for very situational reasons so the harm of breaking those links two or three years later is going to be close to zero. Nice that the content's new home is a free subdomain which will hopefully outlast the maximum lifespan of a domain name funded by an individual person.

Why It's Happening

It costs money to run a service like this, and money's a little tighter here this year. I've been looking through my recurring monthly expenses for things to cut and 666a sticks out because at around 300kr per month it's one of the larger ones.

It also takes time to run a service like this, and I'm feeling a little poorer on that front this year too. In June last year it randomly broke due to an update to the HTML on av.se. Who knows what they'll ship this year that might break it again, or how long it'll take to fix next time, or what I might already be busy doing when it happens.

Been a lot of fun building and operating this, even though Arbetsmiljöverket should definitely just be delivering it themselves directly on av.se. I've ended up effectively having my own personal copy of their diarium database as a result of running this for the past year or so and there's probably some interesting and/or entertaining stuff in that dataset which I'll hopefully have time to dig out over the next couple of months. It'd be cool to mark the final shutdown date with a bit of that.

Accidentally Sending Too Many HTTP Requests

This was originally posted at https://666a.se/news/accidentally-sending-too-many-http-requests and has been migrated here since for long-term hosting.

Arbetsmiljöverket updated their webdiairum back in June. When I updated 666a to work with their new system, I made a coding mistake. The impact of my mistake was that 666a began to send more and more HTTP requests to Arbetsmiljöverket's webdiarium with each day that passed after the mistake.

This was the kind of mistake where it doesn't have very much impact at first, but the impact quietly grows and grows. These are the worst. They're so easy to miss because of how subtle they are on the day you ship them. And then by the time you do notice them, they've grown into a monster. By the time I caught this, it was causing something like 10000 extra HTTP requests per day.

Graph showing a surge in growth around June

It's fixed now. Sorry, Arbetsmiljöverket. I hope the system extra load didn't cause any trouble, although to be honest I doubt I'm the only one monitoring the webdiarium in this way so perhaps it wasn't even noticeable on your end. You can email me any time if you ever need to have a word with me about something like this.

Using AI to help humans translate Swedish labour laws

Over on 666a I provide English translations of Swedish labour laws. For the most part these are based on some translated PDFs that the Swedish government sometimes publish. The government update the laws more frequently than they update the translations though. Providing an up to date resource here meant updating the translations myself, which is a challenging problem.

I used a little bit of AI as part of the solution. But that doesn't mean these are "AI translations". Christ no.

Still from Star Wars bootleg "The Backstroke of the West" with Darth Vader and the caption "Do Not Want"

What's interesting about translating legal text in particular is that you really want lots of uniformity in the outcome. If a particular phrase has been translated a particular way nine times before then the tenth translation should follow the pattern too. This means it's not enough to speak Swedish.

Familiarity with the source text and the existing translations is key. In practice, translating any given sentence becomes a long process of searching the already-translated text for similar words and then reading those existing translations to build an understanding of the prior context. Where I found a good role for AI was in optimising that process, enabling me to spend less time on the manual searching and more time on the reading and understanding.

Take the second paragraph of section 13 of the Working Hours Act for example.

Swedish English
I den dygnsvila som alla arbetstagare har rätt till skall tiden mellan midnatt och klockan 5 ingå. Avvikelse får göras, om arbetet med hänsyn till dess art, allmänhetens behov eller andra särskilda omständigheter måste bedrivas mellan midnatt och klockan 5. Lag (2005:165). The daily rest period that all employees are entitled to shall include the hours between midnight and 05.00. Derogations may be made if the work, in view of its nature, the needs of the general public or other special circumstances, must be carried out between midnight and 05.00. Act (2005:165).

First, I use ChatGPT to break this up into sentence pairs.

Swedish English
I den dygnsvila som alla arbetstagare har rätt till skall tiden mellan midnatt och klockan 5 ingå. The daily rest period that all employees are entitled to shall include the hours between midnight and 05.00.
Avvikelse får göras, om arbetet med hänsyn till dess art, allmänhetens behov eller andra särskilda omständigheter måste bedrivas mellan midnatt och klockan 5. Derogations may be made if the work, in view of its nature, the needs of the general public or other special circumstances, must be carried out between midnight and 05.00.

Then a little more ChatGPT to mulch those sentence pairs down further into pairs of words and phrases.

Swedish English
dygnsvila daily rest period
som alla arbetstagare har rätt till that all employees are entitled to
Avvikelse får göras Derogations may be made
allmänhetens behov the needs of the general public

Once we have those word/phrase pairs generated for all existing translations, we can have a page that automatically lists matches for each word in a given paragraph of source text.

Website admin UI screenshot showing many word/phrase pairs

The results aren't perfect, and what's great is that they don't need to be. Sometimes the AI fucks up the word/phrase pairs, and it doesn't matter. Since we're not removing humans from the process – but rather optimising how the available time is used – it's okay for this to be a little bit sketchy.

What this enables is to pick out any new paragraph that needs translating and instantaneously scan the entire corpus of existing translations for the bits that might be of interest to the human about to produce the new translation. Even after visually scanning the results one time you immediately start to feel a bit confident that you know how you're going to translate some of the legalistic glue phrases. It frees up your remaining attention and time to focus on translating anything that's actually novel about the new paragraph.

In the end I'm not sure if I saved time from this or just spent the same amount of time more impactfully. With the correctness of legal text having such an obvious importance, you end up wanting to invest a certain amount of love into the work just for a sense of hygiene about the outcome. Like if it's too quick, it just doesn't feel done. So in this case I think it's more likely that using AI just made the work more enjoyable and improved the outcome rather than bringing it to an end sooner. Perhaps that's not the standard capitalist narrative about what this technology's benefits are for society, but I'll take it.

Really happy with this. The level of hype around AI is nauseatingly intense and that's leading to a lot of overapplicaton of the tech. There's a decent amount of people using it to fully communicate on their behalf, which I really don't get. It has such a distinctive tone of voice with all those extra adjectives and adverbs, and that uncanny beehive-looking regularity in the structure of the sentences and paragraphs. It's amazing to me that people either don't see how obvious it is or don't feel how unengaging it is once you twig that you're reading something that wasn't important enough to write. Negative experiences like those leave the door wide open to outright cynicism about the tech in general. I'm glad I have a nice example like this to keep my head balanced.

All laws now up to date!

This was originally posted at https://666a.se/news/all-laws-now-up-to-date and has been migrated here since for long-term hosting.

A few weeks ago I mentioned that preparations for updating the English translation of the Work Environment Act were complete. Even more good news now: not only is 666a's English translation of the Work Environment Act now completely up to date, but so is the English translation of the Working Hours act!

As far as I'm aware, right now 666a is now the only place on the web where you can get an up-to-date English translation of Sweden's four most important labour laws. The ones on government.se are still out of date. And in the case of the Work Environment Act, more than a decade out of date.

My favourite thing I learned in the process of updating these translations was in Chapter 7 Section 16 of the Work Environment Act.

The market surveillance authority may procure a sample of goods under a hidden identity according to Article 14.4 j of Regulation (EU) 2019/1020 only if necessary to achieve the purpose of the inspection.

It grants Swedac the power to order stuff under false names in order to verify compliance with quality and safety requirements. This is an implementation of an EU law, and it just stuck in my head because you don't tend to think of quality assurance as a form of espionage, but it actually makes a huge amount of sense when you think about it!

Also found it interesting because I don't think it really seems to belong in the Work Environment Act at all. It certainly has nothing to do with anyone's work environment. I think it seems to have been shoehorned in here for convenience due to its similarities with e.g. Chapter 7 Section 5, maybe to avoid the work of creating a separate Market Surveillance Act or something. I think software engineers have more in common with the people writing laws than any of us might have thought!

Next up, I think I'd like to rescue the Parental Leave Act and the Annual Leave Act from the Swedish government's PDF compost heap. There's nearly a decade's worth of updates missing from the most recently published English translation of the Parental Leave Act too, so that one's going to take a minute or two to get polished and shipped on here.

Let's update the English translation of the Work Environment Act

This was originally posted at https://666a.se/news/lets-update-the-english-translation-of-the-work-environment-act and has been migrated here since for long-term hosting.

The original English translation of the Work Environment Act on 666a was sourced from the government-produced translation on government.se. That's a translation of a decade-old version of the law, so until today there was a big red warning at the top of every page on 666a saying "watch out, this is out of date". Not any more.

Over the past several months I've looked very carefully through every paragraph of every section of every chapter of this law. Most of it is the same as it was in the version the government translated back in 2014 or so. So for those, I've kept the original English translation and removed the warning.

In cases where the wording of a section of the law has changed, I've updated the Swedish text to match the latest version and removed the English translation entirely. The missing English text is replaced with links to GitHub issues where contributors (like you reading this, maybe) are invited to collaborate in public on updating the translations. Those pages are

And in cases where completely new sections have been added, I've done a similar thing. Those are

I don't think it's terribly complicated to translate these few words from Swedish to English. Especially not with so much reference material to work with. The vast majority of the vocabulary in a given paragraph of one of these laws overlaps massively with the vocabulary in the rest of the law.

What I do think is important and challenging, though, is for the translations to feel trustworthy. And for that I think it's important that the work of producing them should be methodical, accountable, and public. So that's why I've set it up as GitHub issues to start with.

In the long term, I'm interested in incorporating this translation process directly into 666a as a first-class citizen feature on equal footing with the email alerts and the labour laws. Requiring a GitHub account might exclude contributors for one thing. But more than that I think there's opportunity in the tooling itself. For example, one thing we'd produce would be a glossary of common legal words, and I think that could be a valuable resource in itself once completed.

But enough daydreaming. What's important right now is that the horrible red "out of date" warning is gone from the Work Environment Act translation on here. And there's now at least somewhere online where the work of updating these translations might actually happen. That's probably our strongest chance of advancing this form of integration at the moment, given the "Ausländer Raus" mentality that's currently so popular in Sweden's national parliament.

We maxed out Sendgrid's free tier

This was originally posted at https://666a.se/news/we-maxed-out-sendgrids-free-tier and has been migrated here since for long-term hosting.

Last week, 666a's daily email volume exceeded the limits of Sendgrid's free tier. This caused a brief email alert service outage, as a number of email notifications were blocked from sending. This is now fixed: I've upgraded 666a's Sendgrid account to the $19.95/month billing tier and re-sent the email alerts that were initially affected by the issue.

This is a total lyxproblem, and a milestone I've been anticipating for a while. 666a's admin section has some email usage graphs which include daily sending statistics, so it's been possible to observe the upwards trend in the daily email volume.

Sendgrid performs some kind of background check on your account before they'll let you upgrade your billing tier and start sending larger volumes of email. I'd already completed this process in advance, months ago in fact, because the idea was to avoid an outage entirely and simply upgrade ahead of time shortly before hitting the limit.

I'd calculated that I had another month or two before it would become necessary to pay. What I hadn't counted on was that my cleanup work after the new Arbetsmiljöverket Webdiarium would be enough to tip us over the limit ahead of schedule. I try really hard to keep this thing running as reliably as possible and dropped the ball very slightly in this case.

The extra bill brings 666a's monthly running costs to somewhere in the 300kr range. It's roughly triple what it was before, but still manageable. This Sendgrid billing tier is overpowered for 666a's current scale, so in the near future I'll be looking into cheaper suppliers with smaller limits.

Later, it might be interesting to investigate the possibility of asking one or more of the central unions or umbrella organisations to help cover some of these costs. First though, I think let's get a whole first year of operation in the rear view mirror, and then see how we're looking in terms of statistics and numbers.

That kind of funding will probably become more achievable the more impressive the usage metrics sound. So if you want a more self-sustaining 666a then spreading the word about the service to your own personal network within the labour movement is probably a way you can help make it happen.

About Arbetsmiljöverket's New Webdiarium

This was originally posted at https://666a.se/news/about-arbetsmiljoverkets-new-webdiarium and has been migrated here since for long-term hosting.

The Work Environment Authority shipped a completely new version of their web search tool last week, which took 666a’s email alerts out of action for a week. It’s fixed now.

This was always my nightmare scenario for 666a. The Work Environment Authority’s search tool was already looking very old when I built 666a. There’s a particular type of “looks old” where you can almost hear the team who maintain it arguing internally for a rewrite.

My fear was that the new version, when it inevitably came, would require JavaScript. The old version served results as plain server-rendered HTML, which is important for a service like 666a because it means you can scrape them quite efficiently with just an HTTP request and an HTML parser. The economics of providing this kind of email alert service would look a lot worse if it became dependent on headless browser automation due to a JavaScript-heavy rewrite of the search tool.

Thankfully this hasn’t happened. And for that, I’m very grateful to whoever’s behind this rewrite. Seriously, thank you. The new version is lovely, by the way, so great job!!

Now that 666a’s an open source project, the full incident response process is public on GitHub. There’s even a project called “Update the email alerts service for the Work Environment Authority's new web search tool” where you can get an overview of each individual task if you’re curious. Always happy to onboard new contributors so if it sparks your curiosity do reach out!

Fixing 666a (again)

So apparently 666a is still capable of surprising me. A few months ago I wrote about the work I'd done to address an issue I've been calling “document lag”. Since then, I've continued to keep a constant eye on the system's reliability. This week, something new cropped up.

The investigation began when I did my usual round of manual checks of Arbetsmiljöverket's public archive, comparing the canonical data there to the notifications I've received recently from 666a. There was a document listed that I hadn't received an email about, which is a worst case scenario for me. The whole point of the service is for that not to happen, so it's my most feared type of bug and basically a priority zero issue. Now that it's fixed, I wanted to write up what was wrong and how I resolved it.

The old system

At the core of 666a was this one cron job called the "day job". When it started, the first thing it did was to check how many documents it saw last time it ran. Then it'd add one to that number and start looking for more.

graph TD;
A[DayJob] -->|Start| B(n = how many documents we've previously found for this day);
B --> C(Try to fetch more documents starting at n + 1);
C --> D{Were there any?}
D -->|Yes| B;
D -->|No| E[Done];

This approach depended on the assumption that new documents would always appear at the end. I'd had my suspicions about this assumption, but it had always help up. Until last week anyway.

Diagnosis

Sometime around Tuesday I noticed a document had been filed backdated to last Friday but never got picked up by 666a. When I checked the data for Friday, I found the old “Day Job” was up to page 95 of the results.

Thing is, the missing document wasn't on page 95. It wasn't on any of the pages after it either. I took a deep breath and began clicking back through the previous pages one by one. Eventually I came to page 84, and there it was.

Screenshot of the Work Environment Authority's search tool showing results corresponding to the page 84 URL linked earlier.

Implications

This design flaw meant that 666a would miss something in the region of 5% of all documents filed. That's a bad enough number that there's no ifs or buts about whether it needed fixing or how soon. This was a "fix-it-today" job.

Fix-it-today jobs are tricky these days. We've got a lot going on at home. I have about 30 minutes tops in a given day for something like this. So not only did I need an immediate fix for a design-level defect, but also it needed to be a small code change that would be quick to implement and YOLO into production.

The fix

By the time the kids were in bed the quick fix had occurred to me: empty the search result cache for each day before updating it. This leads to the exact same algorithm as before, except with a "delete" step added at the very beginning.

graph TD;
A[DayJob] -->|Start| F(Clear cache for this day)
F --> B(n = how many documents we've previously found for this day);
B --> C(Try to fetch more documents starting at n + 1);
C --> D{Were there any?}
D -->|Yes| B;
D -->|No| E[Done];

That forces the job to re-fetch everything from scratch, beginning at page 1. It means nothing gets missed. And importantly, it also made the fix easy to implement. In fact, it was damn near a one line fix.

Version control diff showing the addition of a line that reads “day.searches.destroy_all if options[:purge]” in a file called “app/jobs/work_environment/day_job.rb”

Scaling it up

The downside of this fix is that dramatically increases the number of HTTP requests necessary to check if new documents have been filed. My informal budget I set for myself is that I try to keep the amount of requests I send to av.se within the region of 1000 per day so that I'm as good as unnoticeable in terms of the load I put on their service.

As part of my previous fixes to account for backdated filings I'd programmed 666a to check the past 64 days every day. Checking all 64 on a cold cache would blow that informal 1000 requests budget. I'm really happy with the compromise I came up with here. Instead of checking every day sequentially, like 1.days.ago, 2.days.ago, 3.days.ago, 4.days.ago, 5.days.ago and so on up to 64, I switched to powers of two. So instead I'm checking 1.days.ago, 2.days.ago, 4.days.ago, 8.days.ago and so on.

In practice this won't lead to any significant notification delays, because the vast majority of documents are listed the day after their filing date anyway. And the decrease in days checked compensates perfectly for the increase in number of requests necessary to check a day. I actually keep statistics about how many requests to av.se I make per day, and the chart really drives home how steady the numbers stay despite the change.

Bar chart with a y axis ranging from 0 to 1500 and an x axis ranging from 2023-10-30 to the present day. The bars are typically between 700 and 1200 high. Near the end, a pink arrow and text annotates one of the bars as “First day with new algorithm”.

What's next?

It's great fun having this kind of side project to look after. This one in particular feels like maintaining an old motorbike or something. A Rails app with a cron job that sends email notifications is kind of a retro combination at this point. And it's running beautifully now. Dead happy with it.

By now, 666a has processed over a quarter of a million documents and sent over a thousand notification emails. It's crystal clear the demand exists for the service. The daily email volume still fits within SendGrid's free tier, but it's growing steadily enough that I've already taken the time to get pre-approved for a paid subscription when the time comes.

If I'd shipped it as a “beta” – and maybe I should have – this would probably be the moment I'd officially say it was “out of beta”. Right now my worst fear would be for somebody at Arbetsmiljöverket to suddenly ship a redesign of the diarium search feature. Especially if that redesign depended on JavaScript and reworked all the logic around sorting, filtering and pagination. So let's all cross our fingers for that not to happen!

Night Work, Tech, And Swedish Labour Law

This was originally posted at https://666a.se/news/night-work-tech-and-swedish-labour-law and has been migrated here since for long-term hosting.

Last week’s news about Spotify’s night work ruling from the administrative court was a landmark moment for the Swedish tech industry. It’s the latest in a series of news stories about tech employers trying and failing to circumvent the Swedish labour market model through legal maneuvers. There’s a clear pattern forming: it doesn’t work.

This was the original Work Environment Authority case that inspired the idea for 666a. The case had a lot of twists and turns, and it was too easy to go a week without noticing an important new filing, so I longed for a work environment email alert service to inform me automatically. And then when something did come up, explaining it to people was made more difficult by the lack of linkable English translations of relevant legislation.

Now that the case is drawing to a close and my dream of being able to explain the story and its context in terms of the laws involved is finally possible, here’s a chronological walkthrough.

The daily rest period

Section 13 of the Swedish Working Hours Act protects the right to a daily rest period. This must be at least 11 consecutive hours in a given 24 hour period. It must also include the hours between midnight and 05:00.

This is a problem for employers whose businesses involve software systems with the potential to break during those hours. In tech it’s commonplace to organise an on-call rota for this work, which means engineers take turns. If something breaks outside of normal business hours, a service like PagerDuty phones the engineer on call and wakes them up to fix the problem.

This practice isn’t legal in Sweden unless certain checks and balances are in place. Despite this, some tech employers have ignored the law, instructing employees to work during the night anyway.

Safety representative training

Chapter 6 Section 4 of the Swedish Work Environment Act creates a joint responsibility, shared by both employers and their employees, that safety representatives must receive the training necessary to perform their role.

Ensuring that employers’ personnel practices are compliant with the Working Hours Act is exactly the kind of thing safety reps are meant to do. The Swedish tech industry’s low engagement with the country’s labour movement has enabled years of non-compliance by many employers. Safety representatives without union support – who may well receive all their training from the employer despite the clear conflict of interest this entails – often won’t notice the violation, or are easily instructed to ignore it.

This pattern is exactly why the government’s 2023 instructions to the work environment authority to increase the number of safety reps “regardless of union membership status” met with so much backlash from the central unions. Safety reps without union support are easily sidelined. It’s my understanding that cases of full-blown employer co-optation of entire work environment committees aren't unheard of.

Exemptions by the Work Environment Authority

Section 19 of the Swedish Working Hours Act gives the Work Environment Authority the power to grant exemptions to the night work ban imposed by section 13. In 2023/016334-18, they explained the criteria for the exemptions in some detail.

It appears from practice that the exemption option regarding the night work ban must be applied restrictively and is intended for situations that satisfy important societal interests and urgent service needs.

The work that is granted an exemption from the night work ban thus either needs to support a directly exempt activity or in itself be of great societal interest. It is also required that there is an important societal interest in the work being carried out at night.

In blunt terms, "we make more money when the servers are up" doesn't cut it. If you're a SaaS business and one of your customers depends on your product to deliver a socially critical service then you can still get an exemption because of that, but otherwise there's only one other route to legal night work.

Legal night work through collective bargaining

Section 3 of the Swedish Working Hours Act grants workers the flexibility to negotiate away the night work ban imposed by section 13 through collective bargaining with the employer.

This is one of my personal favourite Swedish laws. I think there's just such an instinctive fairness to it. To agree to be randomly awoken in the night to urgently defend your employer's business is to take a level of responsibility more commonly associated with a parent of a newborn baby. It's fair for workers willing to invest this much of themselves in a business to expect their employer to respect them as an equal counterpart in negotiations about working conditions and the like.

This is the point Spotify's founding team missed when they first threatened to withdraw the company from Sweden back in 2016.

Think how amazing it would be if Sweden became the country where the employees became part-owners of the companies where they work. It suits us and our culture perfectly. We as owners are prepared to share. If anything, politics should promote that ownership spreads and creates solidarity.

It sounds alright superficially, but the words turns to ashes in your mouth once you understand that small-time shareholders don't have any meaningful say in working conditions compared to the co-determination already provided for by Sweden's world-leading labour law. Once you're being woken up at 03:00 to fix servers, the board's fiduciary duty to shareholders may even be in conflict with your most pressing material needs (i.e. a full night's sleep as often as possible). That's why I think section 3 is such a clever piece of legal judo to empower workers. You're such a key worker that you sometimes need to get up in the night like a superhero? Then you get a seat at the table when big decisions are being made.

Fines for non-compliance

Section 24 of the Swedish Working Hours Act imposes fines for employers who violate the night work ban imposed by section 13.

I'm not as impressed with this law as I am with the flexibility of section 3's compliance via collective bargaining. Klarna's fine was 1,094,471kr and Spotify's was only 356,000kr. Fines this small are not a serious financial deterrent.

There is also the soft penalty of the brand damage an employer incurs by flouting labour laws, but most employers aren't as high profile as Klarna or Spotify, so this penalty is much smaller for them. And even in cases where this leverage exists, it's a severe flaw for the system to depend on individual union representatives or safety reps taking on the personal risk of actually using that leverage to achieve compliance. Fear of retaliation has a very powerful chilling effect.

The right to appeal

Section 29 of the Swedish Working Hours Act makes it possible to appeal the Work Environment Authority's decisions in an administrative court.

Something I'll wonder about for the rest of my days is how much impact the events of the Tesla strike had on Spotify's appeal. In a regular year, I reckon the sheer brand power that Spotify wields in Swedish society might have been enough to browbeat an off-guard administrative court into granting their appeal.

But 2023 wasn't a regular year. Of particular note were Tesla's failed Solna district court case and their loss on appeal in the Norrköping district court. I can't shake the feeling that all this racket Tesla made might have awoken an awareness among Sweden's legal profession that a couple of powerful employers were attempting a sudden Americanisation of the Swedish labour market through courtroom shenanigans.

Enforcement

Section 22 of the Swedish Working Hours Act empowers the Work Environment Authority to issue any prohibitions necessary to get employers to follow the law. Section 23 imposes penalties ranging from fines to up to a year of imprisonment for failure to comply with prohibitions under section 22.

It seems unlikely the Spotify case will come to this. Their stance is clear: they'll instruct their overseas workforce to pick up these tasks rather than engage in collective bargaining with their Swedish workforce.

I think that's a really exciting move – part of a strategy conceived in early 2023, when they filed for their night work ban exemption the day after the formation of the Spotify Unionen club. Back then, it had been years since Unionen had last invoked section 45 of the Swedish Co-Determination Act , which I bet made this seem like more of a risk analysis slam dunk than it might seem now.

Operating 666a

In the final quarter of 2023 I launched my little side project 666a, which is a service providing work environment email notifications for union reps and people like that. It took a few months of work to build something shippable, and I've been refining it ever since to increase its reliability. I thought it'd be nice to share a glimpse of what that refinement work looks like. This is gonna be a technical one, so apologies to anyone who preferred the union propaganda.

How 666a works

The beating heart of 666a is a daily cron job that checks for new public filings on the Work Environment Authority's website and sends email notifications whenever it finds one matching a user's subscription criteria.

Filings are published with one day of delay, which means Monday's filings become available on Tuesday and so on. So each day, 666a scans the filings from the previous day.

Backdated filings and "document lag"

The complicating factor here is that not all Monday's filings are immediately available on Tuesday. In fact, they might not even be filed at all until next Friday. This is a phenomenon I've been referring to as "document lag". The Work Environment Authority isn't an API: it's an organisation powered by people, interactions, emails, and even good old fashioned physical mail. This makes for a much more socially constructed model of time than I'm used to in my everyday tech work where machine-generated timestamps with millisecond accuracy are the norm.

I didn't spot this nuance until after launch. I take the responsibility of operating this service really really seriously, and I'm not comfortable with the idea of anyone missing out on important information because of a detail like that. So I've been slowly tweaking the design of the system to meet this requirement.

Manually triggered backfill

My first move once I understood the system was missing some of the data was to start manually triggering the scan job from time to time. I was very deliberate about designing the actual jobs around this kind of versatility, so a bit of manual intervention was easy and didn't require any code changes. This is more or less what I'd run in the rails console from time to time.

WorkEnvironment::DayJob.perform_now("2023-11-04")

Doing this every day was a labour-intensive approach, but it was a nice way to feel out the scope of the problem. Took about a week for this to give me a nice clear sense of how far back stuff was typically getting backdated.

Scheduled backfill

Based on that informal feel for the typical lag between document filing dates and their actual first appearance, I began scheduling a bunch of backfill jobs like these.

scheduler.cron("0 14 * * *") do
  WorkEnvironment::DayJob.perform_later(
    2.days.ago.strftime("%Y-%m-%d")
  )
end

These have been running nicely since early December. For most days, the average document lag is only about a day or two. So except for the occasional rogue document filed 30 days after its official filing date, this was mission accomplished.

Christmas

The arrival of Christmas unlocked a new level of this puzzle. Suddenly, my daily document count graph flatlined. Everybody had buggered off to watch Donald Duck, and even the steady everyday drumbeat of the asbestos removal company filings fell silent.


      Bar chart with y axis going up to 1500 and x axis of dates ranging across December 2023.
      The first three weeks of the month average between 500 and 1000 documents per weekday.
      The final week averages zero.
Documents per day in December 2023, as of New Year's Eve

This would be no big deal, except by this point I'd also backfilled the data well into 2022. And the December 2022 graph's final week looked nothing like this.


      Bar chart with y axis going up to 1000 and x axis of dates ranging across December 2022.
      The first three weeks of the month average between 500 and 1000 documents per weekday.
      The final week averages 250.
Documents per day in December 2022

I immediately suspected that this was another case of document lag. In other words everyone's off for Christmas, and when they get back they'll backdate all the filings that were missed during the holidays.

Quantifying document lag

The only way to find out if my document lag theory was the right explanation was to ignore the problem, enjoy Christmas, and wait and see. It probably didn't matter anyway: I don't think many world-changing public filings are dropping during the Christmas season.

I did want some way to visualise the issue when the backdated filings began to trickle in though. So I created a new chart displaying the document lag for each day since launch. The bar height here represents the average number of days difference between that date and the true chronological first appearance of the documents officially filed on that date.


      Bar chart with y axis going up to 10 and x axis of dates ranging across Q3 of 2023.
      Until late December the values average at one or two with occasional blips.
      After December averages above 5 are more tpical.
Average document lag per day since launch day

The Christmas spike represents the fact that the documents officially filed on e.g. December 27th were in fact not filed until January 3rd when people began returning to work.

Next Steps

I think the scale of this phenomenon will probably more or less double for Midsummer, so that's what I want to be prepared for next. Once the dust settles from the Christmas period, I'm thinking I'll figure out the maximum document lag measured in that week, double it, and then wire up the scheduler to backfill that far back every single day. I want Midsummer to run smoothly even if I'm too busy to do any manual interventions in the moment.

By the way, if you're a tech worker in Sweden and the events of the past year or so have got you thinking some new thoughts about labour relations in our industry, you might wanna check out 666a more closely. You can grab your employer's organisationsnummer from Bolagsverket's company search tool and then subscribe to get notified (for free) about their correspondence with the Work Environment Authority. I'm also hosting web versions of the Swedish government's unofficial English translations of the Work Environment Act, the Co-Determination Act and the Employment Protection Act, which can be useful resources to know about depending on how 2024 unfolds at your job. Check it out!

Incident Report

This was originally posted at https://666a.se/news/incident-report and has been migrated here since for long-term hosting.

This weekend there was a minor incident where 666a over-alerted a little bit, resulting in a total of less than 100 email alerts to be sent in error. No data loss or privacy breaches occurred as part of this incident, just a few emails getting sent that shouldn't have.

Here's the explanatory email I sent to the folks who got some unnecessary emails.

Hey folks

Earlier today 666a went a bit haywire and started sending loads of email notifications about arbetsmiljöverket filings from April. It’s fixed now and you shouldn’t see any more.

I take operating this service really seriously and wanted to get in touch and explain. I’ve been tweaking the diarium update algorithm this week to try to avoid missing documents if they’re filed late and then backdated to earlier in the week. While doing so I made a small coding mistake that turned on email notifications for all documents.

Normally only a fraction of documents get email notifications sent about them. I’ve got 666a slowly backfilling its database with the entire 2023 dataset because I think I can operate the service best with at least one complete year of data history. Email notifications are switched off for those historical documents but my change this week accidentally turned them on.

Rest assured it won’t happen again, and as you can tell I'm very biased towards overalerting rather than ever risk someone missing something, so I think that's at least not completely terrible.

Henry

English translations of Swedish laws

This was originally posted at https://666a.se/news/english-translations-of-swedish-laws and has been migrated here since for long-term hosting.

The work environment email alerts launch a couple of weeks ago has gone great. It's operating really smoothly now and delivering email alerts to way more people than I dreamed would sign up this early. So I'm moving to the next phase, which begins today.

Linked here is an English translation of chapter 6, section 6a of the Swedish Work Environment Act. This is the law that 666a is named after. Until today the English version of it hasn't had its own URL. You could link to PDFs containing it somewhere on page 15, or pages that mention it in passing, but there was no way to send your English-speaking colleague a convenient link to it to help them understand their rights.

The data entry work that's gone into creating this resource was gruelling. The reason it was worth the trouble is simple. I saw first-hand during the Spotify campaign how the absence of this kind of resource is a strategic weakness for Sweden's labour movement, with its dreams of organising the country's influential tech immigrant workforce.

People move to this country to work in tech. Sweden's bursting with cool international employers whose company language is English. So you get off the plane on Saturday, unpack on Sunday, roll into the office on Monday and just get started. No language barrier, everything's in perfect English.

Later that week you stop by the bank during lunch to try to open an account. Not so easy. The person helping you speaks great English, but the forms are in Swedish. It takes longer than expected and makes you return late from lunch. Right from the start, your new life in Sweden is defined by this contrast between the comfort and familiarity provided by your employer and the friction and inconvenience of Swedish society at large. It's a barrier to integration.

Ten years ago, the Swedish government produced unofficial English translations of key laws. These were published as PDFs on government.se, where they remain to this day. The laws themselves have been updated repeatedly since then, but not all the translations have been updated to match. To a lawyer, the failure to maintain such an important resource might seem like the headline problem. But in tech culture, it's actually the PDF thing.

It's impossible to send someone a link to a specific part of a PDF, which means sending a colleague a link to e.g. section 11 of the Co-determination Act in English is impossible. You have to send them the PDF link and tell them "scroll down to xyz" instead. Many people won't.

And the dominant mobile device among this demographic – the iPhone – provides no immediate means of generating a machine translation if you send someone a link to a resource in Swedish. They can copy-paste the text into Google Translate if they're really keen. But many people won't.

The experience of receiving a PDF link is worse too. A web page will usually have metadata configured so that a link pasted into a chat platform such as WhatsApp or Slack will appear with a short description or excerpt of the page's content. PDFs can't do this, so on most platforms you just see a bare link instead and have to make a leap of faith that it might contain something useful. Many people won't.

This friction is a serious barrier to increasing engagement. Tech people live on the internet in a way that politicians and lawyers just don't. In our interactions with online services we perceive subtle signs of value or quality or trustworthiness that people who are less terminally online might not.

Starting today, 666a is taking one of those decade-old translations and hosting it as proper linkable web content. You can browse the full text of the Work Environment Act in Swedish and English side by side. And when you find the section you're looking for, you can grab its URL for bookmarking or sharing. So finally there's a way to send someone a link to chapter 6 section 6a in English.

The decision to include the original Swedish alongside the unofficial English translation is deliberate too. Those little moments of exposure will help grow your vocabulary. Integration isn't just about spoon-feeding us translations forever. Any immigrant's long-term goal is always language acquisition. Thoughtful design choices in services we depend on can support that long-term goal even as we focus on solving our short-term everyday problems.

I'll repeat this process for more laws over the coming weeks. There are some particularly important ones that are my top priority, like the Co-Determination Act and the Employment Protection Act. Please do email me at henry@666a.se and let me know if there's one you think is important not to miss.

My big dream for this feature would be to secure some funding from somewhere to spend on updating all the translations. I think there's almost limitless potential here. For example, I would absolutely love to commission professional Arabic translations of all these laws and host them right here alongside the English ones. I'm convinced that meeting immigrants where we are is the way to make us feel seen and wanted, and inspire us to engage more with Swedish society.

But first things first. Here's an English copy of the Work Environment Act that's ten years out of date.

Announcing 666a

This was originally posted at https://666a.se/news/launch-announcement and has been migrated here since for long-term hosting.

Public filings at the Swedish Work Environment Authority are essential for understanding organizations and the current work environment of companies. Keeping up to date is a prerequisite for driving sustainable development in the Swedish labour market. 666a is a modernization of Sweden's principle of public access to information, making information automatic, customized, and multilingual, rather than merely available.

Origin

The idea for this tool comes from personal experience with union involvement in the workplace. As a union representative at Spotify, a problem I often encountered in my work was the difficulty of keeping up to date with public filings at the Work Environment Authority, which was information that was crucial to our campaign to secure a collective bargaining agreement.

666a is the tool I was missing. It's finally here.

If you have any questions, feedback, or thoughts on how the tool can be further developed, email me at henry@catalinismith.se.