Repository navigation
initial data model: org, user, workspace, env, membership, tokens, audit - #2
Open
catalysync wants to merge 42 commits into
Open
catalysync wants to merge 42 commits into
catalysync wants to merge 42 commits into
Conversation
# Conflicts: # alembic/env.py # src/nagara/main.py
catalysync
force-pushed
the
feat/initial-data-model
branch
from
April 25, 2026 09:02
ff4ccbf to
68983e1
Compare
catalysync
force-pushed
the
feat/v0-infra
branch
3 times, most recently
from
April 26, 2026 11:16
d851a04 to
fecd799
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First vertical slice of the data layer. Stacked on #1 — must merge after that PR (depends on the alembic scaffolding it adds).
Models
Org— tenant root withauth_provider(local|zitadel|workos),auth_configjsonb, billing status, soft deleteUser,Group,GroupMember— humans + groups scoped to one Org, both withexternal_idcolumns for SCIM/IdP linkageWorkspace— the project (membership boundary, asset boundary)Environment— first-class within a workspace; partial unique index enforces one default env per workspaceMembership— polymorphic principal (User XOR Group), 5-role enum (owner/admin/editor/viewer/guest), check constraint enforces the XORAPIToken— PATs + service principals, hash-only storage, prefix shown in UIAuditEvent— append-only authn/authz log,request_idcorrelation,inetip on Postgres /String(45)on sqlitePlumbing
nagara.db.session— async engine +async_sessionmaker+get_sessionFastAPI depnagara.db.mixins—UUIDPrimaryKeyMixin,TimestampedMixin,SoftDeleteMixinnagara.models— single import that registers every table onBase.metadata(consumed by alembic env + tests)ruff check --fix+ruff formatautomaticallyEndpoints
POST /orgsPOST /workspaces— auto-creates thedefaultEnvironment in the same transactionGET /workspaces?org_id=...POST /workspaces/{id}/members— accepts user XOR group via 422-on-violation pydantic validatorTests
118 passing; every model has schema + insertion tests, every endpoint has happy-path + duplicate + validation cases.
Test plan
just checkcleanjust migrateapplies19574c9d_initial_schemacleanly against a fresh dbalembic downgrade base && alembic upgrade headcycles cleanlyalembic checkreports "No new upgrade operations detected"curl -X POST http://127.0.0.1:8000/orgs -d '{"slug":"acme","name":"Acme"}' -H 'content-type: application/json'returns the new org with idslug='default', is_default=trueNotes for review
AssetandSubscriptionfrom the planning doc are intentionally deferred — scope this PR to the bedrock Org/Workspace/Membership sliceroleis the conservative 5-role enum from the planning doc; we'll trim to 3 if UI feedback supports it