RSSAmplifier

Blog

atlas9

A journey to build a better software stack.

atlas9.devRSS feed ↗12 posts

Latest posts

Todos, Traces, Bot Keys, and Grant Cleanup

Here's what landed since the last update. Todos I need to start exercising the code with a dummy product feature, so I added a todo list feature to apps/demo . Lists group items. Items have a title, notes, status ( open , in_progress , done ), and an optional assignee who must be a tenant member. Lists and items each have their own capability set. Trace Logging core/tracelog collects JSON log…

Code Gen, Logging, and Audit

A quick update on recent work in apps/demo . Restructuring The api_foo.go / impl_foo.go split got pushed further — implementation files now live in api/api_impl , a separate package from the type and route definitions. The API contract is easier to browse without the implementation in the way. Code Generator api/api_gen parses the API package using go/packages and generates: API.md — endpoint…

Bot, Domains, SSO, Access, and Cleanup

I've been steadily chipping away at my TODO list. Although the code is currently in a rough state, it's been almost a couple months since I pushed an update, so I figured it's time to write a quick update blog post. Most of the work has gone into the apps/demo code. I decided to avoid thinking about the proper place for code (e.g. does it belong in core) for now. Once the dust has settled, I hope…

Roles, tenants, rate limiting, and a dashboard

Another grabbag of updates, focused on multi-tenancy, access control, rate limiting, and a dashboard UI. tenants and members The demo app now has tenants – namespaces for resources. Users can create tenants, invite members, and manage membership. If you invite someone who doesn't have an account yet, the invitation is stored as "pending" and resolved when they register. Each user has a personal…

Adding an outbox, mail, tokens, CSRF, and more

This post is a grabbag of updates from the last couple weeks, including a background task system, sending email, cross-origin request forgery protection, one-time tokens, and more. outbox Applications usually need a way to do work in the background. One reason for this is that it's helpful to avoid lots of work within the lifecycle of an HTTP request, especially when the work to be done depends on…

Publishing the core

After many weeks of hemming and hawing, going to and fro, I decided it's time to put some actual code out into the world. A lot of code has been written, lots of experiments and ideas, notes, scribbles, thoughts, questions, and hundreds of millions of tokens (226M apparently!) worth of conversation with Claude. It's been fun and educational to explore topics in depth, reflect on all I've learned…

My setup for integration tests in Go with embedded-postgres

Today, I set out to write some integration tests. Since I'm using Postgres, one hurdle people often run into is how to get a smooth, fast experience while running tests against a test database. A lot of people like testcontainers or running a long-lived Postgres container in Docker. I personally don't like the overhead of this extra machinery – it seems simple, but in my experience it ends up…

Digging into UUID, ULID, and implementing my own

I needed to figure out what ID type to use for atlas9. Initially, I reached for UUIDv7, which seemed like the obvious choice: it's the new version of UUID that incorporates years of experience and wishes. It's sortable, which seems nice, and probably plays nicely with databases – I'm guessing that if your UUID is a primary key, new IDs will be inserted closer to each other, rather than spread…

Modeling identity and access hierarchy in Postgres with ltree

Can Alice edit this blog post? Can Bob comment on that document? Can product executives modify the draft quarterly report? How do applications answer these questions about who can do what? Essentially, the question is can user U take action A on resource R? – can Alice (user) edit (action) this blog post (resource)? You could imagine keeping a grants table in your app that has a row for every…

The challenges of soft delete

Software projects often implement "soft delete", maybe with a deleted boolean or an archived_at timestamp column. If customers accidentally delete their data, they can recover it, which makes work easier for customer support teams. Perhaps archived records are even required for compliance or audit reasons. I've run into some trouble with soft delete designs. I'll cover those, and ponder ideas for…

Building an access framework using Cedar

I’ve been pondering how to provide a robust foundation for access control in atlas9. By “access control”, I mean answering questions like “can Alice edit document Y”. Access control can be tricky – it’s simple at first, but the complexity reveals itself slowly over time, and one day the system is complicated, poorly understood, fragile, and changes become difficult, slow, and risky. I wish we…

Building a better software experience

atlas9 is about an itch I need to scratch. There is so much stuff to figure out in software projects: API design, databases, builds, deploys, async tasks, auth, workflows, releases, docs, flags, config, tests, telemetry, monitoring, logs, infrastructure-as-code, and on and on. Large amounts of energy (time, emotion, money) is spent on this stuff. And when teams get this stuff wrong, even more…