Show HN: SnackBase – Open-source, GxP-compliant back end for Python teams
57 points
11 hours ago
| 5 comments
| snackbase.dev
| HN
Hi HN, I’m the creator of SnackBase.

I built this because I work in Healthcare and Life Sciences domain and was tired of spending months building the same "compliant" infrastructure (Audit Logs, Row-Level Security, PII Masking, Auth) before writing any actual product code.

The Problem: Existing BaaS tools (Supabase, Appwrite) are amazing, but they are hard to validate for GxP (FDA regulations) and often force you into a JS/Go ecosystem. I wanted something native to the Python tools I already use.

The Solution: SnackBase is a self-hosted Python (FastAPI + SQLAlchemy) backend that includes:

Compliance Core: Immutable audit logs with blockchain-style hashing (prev_hash) for integrity.

Native Python Hooks: You can write business logic in pure Python (no webhooks or JS runtimes required).

Clean Architecture: Strict separation of layers. No business logic in the API routes.

The Stack:

Python 3.12 + FastAPI

SQLAlchemy 2.0 (Async)

React 19 (Admin UI)

Links:

Live Demo: https://demo.snackbase.dev

Repo: https://github.com/lalitgehani/snackbase

The demo resets every hour. I’d love feedback on the DSL implementation or the audit logging approach.

threecheese
1 hour ago
[-]
So much of new open source code feels like folks just sharing their Claude tokens with each other, after the fact. I’m having fun just gluing stuff together with my Claude tokens.

It’s unfortunate that so many of these projects just whither away, blasts of commits with hundreds of files but nothing changed in months.

reply
dkoy
8 hours ago
[-]
Briefly checked out the repo and demo, looks neat!

Bookmarked to keep a tab on for future reference.

I noticed that SQLAlchemy (an ORM) is part of the stack, and that “Postgres support” is in the roadmap. For people coming from Supabase and the like which is Postgres-first, some upfront clarification around which database is already supported, would be helpful.

reply
lalitgehani
8 hours ago
[-]
Thanks for the kind words and the bookmark!

You're right. Since I use SQLAlchemy, the core is already database agnostic. Swapping the connection string to Postgres actually works for most features right now.

I listed it as "Roadmap" only because I haven't finished the full end-to-end test suite for Postgres yet, and I wanted the default "Quick Start" to be a zero dependency SQLite setup. I am also working on native read/write splitting so that the system can properly leverage scaling architectures (like Amazon Aurora's single-writer / multi-reader clusters) out of the box.

I'll make sure to clarify in the docs that it's currently "experimental" rather than missing. Appreciate the feedback!

reply
notpushkin
8 hours ago
[-]
This is really cool. I probably won’t be using it directly, but will definitely study some architecture and implementation decisions.

> Compliance Core: Immutable audit logs with blockchain-style hashing (prev_hash) for integrity.

Had this in the back of my mind for a while now, too. In terms of prior art, Keybase had been doing something similar, but with Merkle trees.

> I’d love feedback on the DSL implementation

Could you tell in a bit more detail why you decided to go with your own DSL here? :)

reply
lalitgehani
7 hours ago
[-]
Great question!

Keybase's Merkle approach is elegant for their use case (efficient proofs without revealing the full chain), but I went simpler with a linear chain because:

1. Audit trails are inherently sequential - they're ordered by time and typically read/written in order. Merkle trees shine for unordered data where you need efficient inclusion proofs. 2. Verification simplicity - with a linear chain, integrity verification is just "walk the sequence and check that each entry's previous_hash matches the prior entry's checksum." O(n) and dead simple. 3. Storage efficiency - each entry stores two SHA-256 hashes as strings. No tree overhead. 4. Regulatory fit - for GxP/CFR Part 11 compliance, the requirement is tamper detection, not zero-knowledge proofs. A linear chain detects any modification equally well.

That said, if I ever need selective verification (prove entry #500 is valid without transmitting the full chain), I'd revisit Merkle. The implementation is in src/snackbase/infrastructure/persistence/repositories/audit_log_repository.py if you're curious.

On the custom DSL: This was the biggest architectural decision in SnackBase. Here's the honest breakdown:

Why not just use existing options? >Approach: Python eval() >>Why I didn't choose it: Security nightmare - can't safely let users store arbitrary code in the database

>Approach: CEL (Google's Common Expression Language) >>Why I didn't choose it: Battle-tested, but heavy dependency and less control over semantics

>Approach: JEXL/JSONLogic >>Why I didn't choose it: Another runtime to learn, harder to integrate with my macro system

>Approach: Pure JSON rules >>Why I didn't choose it: Becomes unreadable for complex expressions

What drove the decision:

1. Permissions are database-storable - rules live as strings in the permissions table, editable via API and admin UI. I needed something safe to parse and evaluate at runtime. 2. Sandboxed execution - the DSL only exposes specific operations (==, in, @has_role(), etc.). No imports, no file access, no arbitrary code. Even if someone compromises the admin UI, they can only express logic within the vocabulary I provide. 3. Syntax for non-programmers - "@has_role('admin') and @owns_record()" is more approachable than Python lambdas when you're building permissions in a web UI. 4. Macro integration - the @ prefix ties into my SQL macro system, letting users define reusable business logic like @is_department_head() that executes database queries.

The trade-off:

It's 700+ lines of lexer/parser/evaluator code I have to maintain. Every edge case (null handling, type coercion, short-circuit evaluation) needs explicit test coverage. Debugging a failed rule means returning syntax errors at position X rather than a stack trace.

If I were starting fresh today, I'd give CEL harder consideration. But since permissions are a core differentiator for SnackBase, having full control over the semantics has been worth it—especially for field-level access control and the wildcard collection system.

Implementation files if you're interested in it: - src/snackbase/core/rules/lexer.py - tokenizer - src/snackbase/core/rules/parser.py - recursive descent → AST - src/snackbase/core/rules/evaluator.py - async evaluation with short-circuiting

Happy to go deeper on any of this!

reply
mring33621
8 hours ago
[-]
I'm not sure the AGPL license is a good choice for this.

None of Django, Rails, Pocketbase or Supabase, which I think count as competitors, use AGPL.

Unless you can clarify that custom hooks and schemas are outside of the AGPL license, SnackBase may be a non-starter for commercial use.

reply
lalitgehani
8 hours ago
[-]
Fair point.

Honestly, I picked AGPL mainly to prevent "cloud wrapping". I definitely don't intend for your business logic to get infected by it.

In my view, the custom hooks and schemas are "content/configuration" rather than derivative works, but I get that running in-process makes that legally murky.

To clear that up, I'll add a specific linking exception (like the Classpath Exception) to explicitly exempt user-defined hooks from the license. I want this to be safe for commercial teams to self-host, just not safe for cloud providers to resell.

reply
nodesocket
1 hour ago
[-]
This looks fantastic. I’m working on a project I wrote in plain Flask. Wish I had seen this previously. I spent an ungodly amount of time on organizations, users, permissions, 2fa, password reset, organization invites.
reply