From 5ce85f43240e344fd92b783709950f761601b486 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Fri, 31 Jul 2026 09:09:23 +0200 Subject: [PATCH] gate: fix worker on_startup to set tenant context per-tenant for plugin activation --- app/core/worker.py | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/app/core/worker.py b/app/core/worker.py index 6abe74b..79ce8e9 100644 --- a/app/core/worker.py +++ b/app/core/worker.py @@ -118,6 +118,16 @@ async def on_startup(ctx: dict[str, Any]) -> None: async_session = async_sessionmaker(get_engine(), expire_on_commit=False) # Activate plugins that are marked active in DB (register event handlers) + # RLS fail-closed requires tenant context for tenant-table writes + from app.models.tenant import Tenant as TenantModel + from app.core.db import set_tenant_context + + async with async_session() as db: + # Load all tenant IDs for per-tenant plugin activation + tenant_result = await db.execute(sa_select(TenantModel.id)) + all_tenant_ids = [row[0] for row in tenant_result] + logger.info(f"Worker: loaded {len(all_tenant_ids)} tenants for plugin activation") + async with async_session() as db: for name in registry.resolve_load_order(): plugin = registry.get_plugin(name) @@ -129,21 +139,27 @@ async def on_startup(ctx: dict[str, Any]) -> None: plugin_record = result.scalar_one_or_none() if plugin_record is None or not plugin_record.active: continue - try: - await plugin.on_activate(db, container, event_bus) - logger.info(f"Worker: activated plugin {name}") - except Exception as exc: - logger.error(f"Worker: failed to activate plugin {name}: {exc}") - # Report worker startup errors to Forgejo + # Activate plugin per-tenant with tenant context set + activation_failed = False + for tenant_id in all_tenant_ids: try: - from app.plugins.builtins.forgejo_error_reporter.service import report_error_to_forgejo - await report_error_to_forgejo({ - "message": f"[Worker] Plugin activation failed: {name}: {exc}", - "stack": traceback.format_exc(), - "context": {"plugin": name, "source": "worker_startup"}, - }) - except Exception: - pass + await set_tenant_context(db, tenant_id) + await plugin.on_activate(db, container, event_bus) + except Exception as exc: + logger.error(f"Worker: failed to activate plugin {name} for tenant {tenant_id}: {exc}") + activation_failed = True + try: + from app.plugins.builtins.forgejo_error_reporter.service import report_error_to_forgejo + await report_error_to_forgejo({ + "message": f"[Worker] Plugin activation failed: {name}: {exc}", + "stack": traceback.format_exc(), + "context": {"plugin": name, "source": "worker_startup"}, + }) + except Exception: + pass + break + if not activation_failed: + logger.info(f"Worker: activated plugin {name}") await db.commit() # Register webhook dispatcher on the event bus