# Issue-Core Emission Boundary activity-core owns the decision to spawn a task and the audit trail that says why it spawned. It does not own downstream task lifecycle state after emission. ## Current authoritative endpoint The current authoritative boundary is the issue-core REST API: ```text POST {ISSUE_CORE_URL}/issues/ ``` `IssueCoreRestSink` sends this payload: ```json { "title": "Run SBOM rescan for activity-core", "description": "", "target_repo": "activity-core", "priority": "medium", "labels": ["sbom", "security", "automated"], "due_in_days": null, "source_type": "rule", "source_id": "flag-stale-sbom", "triggering_event_id": "event-or-schedule-key", "activity_definition_id": "activity-definition-uuid" } ``` The expected response contains `issue_id` and may include `issue_url` and `backend`. activity-core stores only the returned task reference in `task_spawn_log`; issue-core remains authoritative for task status, assignment, comments, closure, and cancellation. ## REST versus NATS Keep REST as the active emission contract until issue-core publishes and owns a durable NATS consumer for task-creation commands. NATS is still appropriate for event intake into activity-core, but task creation needs an acknowledged, idempotent command boundary. A future NATS sink must return or later correlate a task reference before it can replace `IssueCoreRestSink`. ## Safe operating modes - `ISSUE_SINK_TYPE=null`: dry-run/audit mode. Task specs are rendered and the workflow records synthetic `null-*` references. This is the current Railiance production setting. - `ISSUE_SINK_TYPE=rest`: live task creation. Sink failures raise out of `emit_tasks`, so Temporal retries and the workflow history make failures visible. Weekly SBOM staleness is safe to evaluate in dry-run mode because the rule contract is deterministic and tested. Do not enable it against the real REST sink until issue-core credentials, endpoint reachability, and duplicate-handling are verified in the target environment. ## Verification Local contract tests cover the rendered weekly SBOM task path and the REST payload shape: ```bash uv run pytest tests/test_integration_event_bridge.py tests/test_issue_sink.py ``` For a live environment, run with `ISSUE_SINK_TYPE=null` first and confirm `task_spawn_log` contains the expected source id, condition, triggering event id, and synthetic task reference. Then switch to `ISSUE_SINK_TYPE=rest` only after a single known-safe rule match creates one issue-core task with the same fields.