@@ -101,6 +101,55 @@ class ServiceMigrationSpec:
101101 ],
102102)
103103
104+ ORG_MIGRATION = ServiceMigrationSpec (
105+ service_name = "auth_org" ,
106+ description = "Organization and membership tables" ,
107+ tables = [
108+ TableSpec (
109+ name = "organization" ,
110+ columns = [
111+ ColumnSpec ("id" , "sa.Integer()" , nullable = False , primary_key = True ),
112+ ColumnSpec ("name" , "sa.String()" , nullable = False ),
113+ ColumnSpec ("slug" , "sa.String()" , nullable = False ),
114+ ColumnSpec ("description" , "sa.String()" , nullable = True ),
115+ ColumnSpec ("is_active" , "sa.Boolean()" , nullable = False , default = "True" ),
116+ ColumnSpec ("created_at" , "sa.DateTime()" , nullable = False ),
117+ ColumnSpec ("updated_at" , "sa.DateTime()" , nullable = True ),
118+ ],
119+ indexes = [IndexSpec ("ix_organization_slug" , ["slug" ], unique = True )],
120+ ),
121+ TableSpec (
122+ name = "organization_member" ,
123+ columns = [
124+ ColumnSpec ("id" , "sa.Integer()" , nullable = False , primary_key = True ),
125+ ColumnSpec ("organization_id" , "sa.Integer()" , nullable = False ),
126+ ColumnSpec ("user_id" , "sa.Integer()" , nullable = False ),
127+ ColumnSpec ("role" , "sa.String()" , nullable = False , default = "'member'" ),
128+ ColumnSpec ("joined_at" , "sa.DateTime()" , nullable = False ),
129+ ],
130+ indexes = [
131+ IndexSpec (
132+ "ix_org_member_org_user" ,
133+ ["organization_id" , "user_id" ],
134+ unique = True ,
135+ ),
136+ IndexSpec (
137+ "ix_org_member_organization_id" ,
138+ ["organization_id" ],
139+ ),
140+ IndexSpec (
141+ "ix_org_member_user_id" ,
142+ ["user_id" ],
143+ ),
144+ ],
145+ foreign_keys = [
146+ ForeignKeySpec (["organization_id" ], "organization" , ["id" ]),
147+ ForeignKeySpec (["user_id" ], "user" , ["id" ]),
148+ ],
149+ ),
150+ ],
151+ )
152+
104153AI_MIGRATION = ServiceMigrationSpec (
105154 service_name = "ai" ,
106155 description = "AI service tables (LLM catalog, usage tracking, conversations)" ,
@@ -369,6 +418,7 @@ class ServiceMigrationSpec:
369418# Registry of all service migrations
370419MIGRATION_SPECS : dict [str , ServiceMigrationSpec ] = {
371420 "auth" : AUTH_MIGRATION ,
421+ "auth_org" : ORG_MIGRATION ,
372422 "ai" : AI_MIGRATION ,
373423 "ai_voice" : VOICE_MIGRATION ,
374424}
@@ -648,6 +698,17 @@ def get_services_needing_migrations(context: dict[str, Any]) -> list[str]:
648698 if include_auth == "yes" or include_auth is True :
649699 services .append ("auth" )
650700
701+ # Auth org tables (only with org-level auth)
702+ include_auth_org = context .get ("include_auth_org" )
703+ auth_level = context .get ("auth_level" )
704+ org_enabled = (
705+ include_auth_org == "yes"
706+ or include_auth_org is True
707+ or (isinstance (auth_level , str ) and auth_level .lower () == "org" )
708+ )
709+ if (include_auth == "yes" or include_auth is True ) and org_enabled :
710+ services .append ("auth_org" )
711+
651712 # AI service (only with persistence backend)
652713 include_ai = context .get ("include_ai" )
653714 ai_backend = context .get ("ai_backend" , "memory" )
0 commit comments