Enforce bounded operation guardrails
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 21s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a028de-e2c8-7732-8521-46a7fc5db82f
This commit is contained in:
tegwick 2026-08-23 12:31:13 +02:00
parent c384f60530
commit 26934e25b9
51 changed files with 1843 additions and 472 deletions

View file

@ -1,8 +1,6 @@
"""Temporal worker entrypoint for activity-core.
Starts two workers (wired up in T20):
- orchestrator-tq: RunActivityWorkflow + its activities
- task-execution-tq: TaskExecutorWorkflow
Starts the ``orchestrator-tq`` worker for RunActivityWorkflow and its activities.
T23: Calls sync_schedules before entering the worker run loop to ensure
all cron ActivityDefinitions have live Temporal Schedules.
@ -35,6 +33,7 @@ from temporalio.worker import Worker
from activity_core.activities import (
apply_sbom_catchup,
emit_tasks,
execute_bounded_operation,
evaluate_instructions,
evaluate_rules,
init_session_factory,
@ -42,13 +41,12 @@ from activity_core.activities import (
log_run,
persist_instruction_reports,
persist_ops_evidence,
persist_task_instance,
resolve_context,
)
from activity_core.db import make_engine
from sqlalchemy.ext.asyncio import async_sessionmaker
from activity_core.sync_service import run_sync
from activity_core.workflows import RunActivityWorkflow, TaskExecutorWorkflow
from activity_core.workflows import RunActivityWorkflow
logger = logging.getLogger(__name__)
@ -57,7 +55,6 @@ TEMPORAL_NAMESPACE = os.environ.get("TEMPORAL_NAMESPACE", "default")
PROMETHEUS_BIND_ADDR = os.environ.get("PROMETHEUS_BIND_ADDR", "0.0.0.0:9090")
ORCHESTRATOR_TASK_QUEUE = "orchestrator-tq"
TASK_EXECUTION_TASK_QUEUE = "task-execution-tq"
async def run() -> None:
@ -106,6 +103,7 @@ async def run() -> None:
load_activity_definition,
resolve_context,
apply_sbom_catchup,
execute_bounded_operation,
log_run,
evaluate_rules,
evaluate_instructions,
@ -115,51 +113,15 @@ async def run() -> None:
],
)
# ACTIVITY-WP-0023-T08: only register the legacy task-execution stub when
# explicitly enabled. Default is orchestrator-only so production does not
# advertise a fake execution surface on task-execution-tq.
enable_task_stub = os.environ.get(
"ACTIVITY_CORE_ENABLE_TASK_EXECUTOR_STUB", ""
).strip().lower() in {"1", "true", "yes", "on"}
task_worker: Worker | None = None
if enable_task_stub:
task_worker = Worker(
client,
task_queue=TASK_EXECUTION_TASK_QUEUE,
workflows=[TaskExecutorWorkflow],
activities=[persist_task_instance],
)
logger.warning(
"TaskExecutorWorkflow stub ENABLED on %s — not for production execution",
TASK_EXECUTION_TASK_QUEUE,
)
else:
logger.info(
"TaskExecutorWorkflow stub not registered "
"(set ACTIVITY_CORE_ENABLE_TASK_EXECUTOR_STUB=true for legacy tests only)"
)
loop = asyncio.get_running_loop()
stop = asyncio.Event()
loop.add_signal_handler(signal.SIGTERM, stop.set)
loop.add_signal_handler(signal.SIGINT, stop.set)
workers = [orchestrator_worker]
if task_worker is not None:
workers.append(task_worker)
from contextlib import AsyncExitStack
async with AsyncExitStack() as stack:
for w in workers:
await stack.enter_async_context(w)
queues = [ORCHESTRATOR_TASK_QUEUE]
if enable_task_stub:
queues.append(TASK_EXECUTION_TASK_QUEUE)
async with orchestrator_worker:
logger.info(
"Workers running — queues: %r (namespace=%r)",
queues,
[ORCHESTRATOR_TASK_QUEUE],
TEMPORAL_NAMESPACE,
)
await stop.wait()