Show HN: SnackBase – Open-source, GxP-compliant back end for Python teams
snackbase.dev52 points by lalitgehani 9 hours ago
52 points by lalitgehani 9 hours ago
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.
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. 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! 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? :) 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! 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. 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.
dkoy - 6 hours ago
lalitgehani - 6 hours ago
notpushkin - 6 hours ago
lalitgehani - 5 hours ago
mring33621 - 6 hours ago
lalitgehani - 6 hours ago