Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -6793,7 +6793,7 @@
"properties": {
"kind": {
"$ref": "#/components/schemas/SurfaceKind",
"description": "Process-level arrival kind. Closed enum; one of http / mcp_stdio / mcp_streamable_http."
"description": "Process-level arrival kind. Closed enum; one of http / mcp_stdio / mcp_streamable_http / in_process."
},
"name": {
"description": "Display name for the new surface.",
Expand Down Expand Up @@ -16380,7 +16380,8 @@
"enum": [
"http",
"mcp_stdio",
"mcp_streamable_http"
"mcp_streamable_http",
"in_process"
],
"title": "SurfaceKind",
"type": "string"
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/agent/promote_seeded_fleet.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from cora.agent.features.version_agent import VersionAgent
from cora.agent.features.version_agent import bind as bind_version_agent
from cora.infrastructure.logging import get_logger
from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID

if TYPE_CHECKING:
from uuid import UUID
Expand Down Expand Up @@ -121,6 +122,7 @@ async def promote_seeded_fleet(
VersionAgent(agent_id=member.agent_id),
principal_id=principal_id,
correlation_id=correlation_id,
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
outcome = OUTCOME_PROMOTED
else:
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/api/_capture_baseline_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@

from cora.api._capture_observer import finite_float
from cora.infrastructure.logging import get_logger
from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID
from cora.operation.ports.control_port import (
ControlAccessDeniedError,
ControlNotConnectedError,
Expand Down Expand Up @@ -189,6 +190,7 @@ async def read(self, capture_code: str, run_id: UUID) -> None:
AppendObservations(run_id=run_id, entries=tuple(entries)),
principal_id=self._principal_id,
correlation_id=self._deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except asyncio.CancelledError:
raise
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/api/_capture_progress_feeder.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
from typing import TYPE_CHECKING

from cora.infrastructure.logging import get_logger
from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID
from cora.run.aggregates.run import FeedHeartbeat, RunObservationLogbookClosedError
from cora.run.errors import UnauthorizedError
from cora.run.features.append_observations import AppendObservations, ObservationInput
Expand Down Expand Up @@ -221,6 +222,7 @@ async def _flush_observations(
AppendObservations(run_id=run_id, entries=tuple(entries)),
principal_id=self._principal_id,
correlation_id=self._deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except asyncio.CancelledError:
raise
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/api/_capture_scan_ingestor.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
from cora.data.errors import InvalidScanFileError, UnauthorizedError
from cora.data.features.ingest_scan.command import IngestScan
from cora.infrastructure.logging import get_logger
from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID
from cora.run.adapters.postgres_run_channel_lookup import PostgresRunChannelLookup
from cora.run.ports.run_channel_lookup import InMemoryRunChannelLookup, RunChannelLookup
from cora.shared.storage_root import normalize_storage_root
Expand Down Expand Up @@ -414,6 +415,7 @@ async def _ingest_one(self, candidate: ScanIngestCandidate) -> _Outcome:
command,
principal_id=CAPTURE_SCAN_INGESTOR_AGENT_ID,
correlation_id=self._deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except asyncio.CancelledError:
raise
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/api/_inference_recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from cora.decision.features.append_inferences.handler import Handler
from cora.infrastructure.logging import get_logger
from cora.infrastructure.ports import AgentInferenceTrace
from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID

_log = get_logger(__name__)

Expand Down Expand Up @@ -84,6 +85,7 @@ async def record(
principal_id=principal_id,
correlation_id=correlation_id,
causation_id=causation_id,
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except InferenceAgentMismatchError as exc:
# Loud like the 403 sibling below: an internal recorder should be
Expand Down
5 changes: 5 additions & 0 deletions apps/api/src/cora/api/_run_witness.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@
from cora.api._capture_progress_feeder import CaptureProgressFeeder, capture_progress_flush_loop
from cora.data.adapters.capture_path_locator import active_scan_transport
from cora.infrastructure.logging import get_logger
from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID
from cora.run.aggregates.run.capture_probes import CaptureProbe
from cora.run.aggregates.run.state import (
CapturePreconditionBypassSnapshot,
Expand Down Expand Up @@ -974,6 +975,7 @@ async def _promote(self, observation: CaptureLifecycleObservation) -> None:
command,
principal_id=RUN_WITNESS_AGENT_ID,
correlation_id=self._deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except asyncio.CancelledError:
raise
Expand Down Expand Up @@ -1128,6 +1130,7 @@ async def _truncate_stale(self, observation: CaptureLifecycleObservation) -> Non
),
principal_id=RUN_WITNESS_AGENT_ID,
correlation_id=self._deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except asyncio.CancelledError:
raise
Expand Down Expand Up @@ -1177,6 +1180,7 @@ async def _record_outcome(self, observation: CaptureLifecycleObservation) -> Non
command,
principal_id=RUN_WITNESS_AGENT_ID,
correlation_id=self._deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
except asyncio.CancelledError:
raise
Expand Down Expand Up @@ -1357,6 +1361,7 @@ async def rebuild_open_captures(deps: Kernel, *, list_runs: ListRunsHandler) ->
),
principal_id=RUN_WITNESS_AGENT_ID,
correlation_id=deps.id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
for item in page.items:
run: Run | None = await load_run(deps.event_store, item.run_id)
Expand Down
23 changes: 23 additions & 0 deletions apps/api/src/cora/infrastructure/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,28 @@
these for backward compatibility with existing trust-internal callers.
"""

SYSTEM_IN_PROCESS_SURFACE_ID = UUID("00000000-0000-0000-0000-000000000023")
"""Seeded Surface UUID for CORA's own in-process work.

Continues the `...0020` / `...0021` / `...0022` sequence above. Written
by a later migration than those three (see
`cora.infrastructure.schema_version.EXPECTED_SCHEMA_VERSION` for the
current newest one) and, unlike them, threaded unconditionally: every
composition-root runtime that calls a handler directly, in-process,
with no HTTP or MCP request behind it (agent tick loops, capture
readers, one-time operator entrypoints) passes this constant as
`surface_id` rather than falling through to `NIL_SENTINEL_ID`. There is
no `Settings` knob gating this, unlike `SYSTEM_LOCAL_CONDUIT_ID`: those
call sites always originated in-process, so naming that fact is a
correction, not a behavior change a deployment might want to opt out of.

Deliberately absent from `cora.infrastructure.observability.surface_context
._SURFACE_KIND_BY_UUID`: that map resolves HTTP-reachable Surfaces only,
and in-process work is by definition never reachable via the HTTP
middleware, the same reasoning that already excludes
`SYSTEM_MCP_STDIO_SURFACE_ID`.
"""

SYSTEM_LOCAL_ZONE_ID = UUID("00000000-0000-0000-0000-000000000030")
SYSTEM_LOCAL_CONDUIT_ID = UUID("00000000-0000-0000-0000-000000000031")
"""Seeded Zone/Conduit UUIDs for the deployment's one real Conduit.
Expand Down Expand Up @@ -319,6 +341,7 @@ def get_mcp_surface_id() -> UUID:
__all__ = [
"NIL_SENTINEL_ID",
"SYSTEM_HTTP_SURFACE_ID",
"SYSTEM_IN_PROCESS_SURFACE_ID",
"SYSTEM_LOCAL_CONDUIT_ID",
"SYSTEM_LOCAL_ZONE_ID",
"SYSTEM_MCP_STDIO_SURFACE_ID",
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/cora/infrastructure/schema_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class SchemaCheck:
expected: str


EXPECTED_SCHEMA_VERSION: Final = "20260831140000"
EXPECTED_SCHEMA_VERSION: Final = "20260831150000"
"""The newest migration this build was written against.

Hand-maintained, and deliberately not derived at runtime: the image does
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/run/adapters/sim_observation_feeder.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from typing import TYPE_CHECKING
from uuid import UUID

from cora.infrastructure.routing import SYSTEM_IN_PROCESS_SURFACE_ID
from cora.run.aggregates.run import FeedHeartbeat
from cora.run.features.append_observations import AppendObservations, ObservationInput

Expand Down Expand Up @@ -111,6 +112,7 @@ async def drain(self) -> int:
AppendObservations(run_id=self._run_id, entries=entries),
principal_id=self._principal_id,
correlation_id=self._id_generator.new_id(),
surface_id=SYSTEM_IN_PROCESS_SURFACE_ID,
)
self._emitted += len(due)
await self._heartbeat_store.append(
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/cora/trust/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from cora.trust._bootstrap import (
SYSTEM_BOOTSTRAP_POLICY_ID,
SYSTEM_HTTP_SURFACE_ID,
SYSTEM_IN_PROCESS_SURFACE_ID,
SYSTEM_LOCAL_CONDUIT_ID,
SYSTEM_MCP_STDIO_SURFACE_ID,
SYSTEM_MCP_STREAMABLE_HTTP_SURFACE_ID,
Expand All @@ -41,6 +42,7 @@
__all__ = [
"SYSTEM_BOOTSTRAP_POLICY_ID",
"SYSTEM_HTTP_SURFACE_ID",
"SYSTEM_IN_PROCESS_SURFACE_ID",
"SYSTEM_LOCAL_CONDUIT_ID",
"SYSTEM_MCP_STDIO_SURFACE_ID",
"SYSTEM_MCP_STREAMABLE_HTTP_SURFACE_ID",
Expand Down
9 changes: 7 additions & 2 deletions apps/api/src/cora/trust/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from cora.infrastructure.routing import (
NIL_SENTINEL_ID,
SYSTEM_HTTP_SURFACE_ID,
SYSTEM_IN_PROCESS_SURFACE_ID,
SYSTEM_LOCAL_CONDUIT_ID,
SYSTEM_MCP_STDIO_SURFACE_ID,
SYSTEM_MCP_STREAMABLE_HTTP_SURFACE_ID,
Expand All @@ -38,8 +39,11 @@
# below.
SYSTEM_BOOTSTRAP_POLICY_ID = UUID("00000000-0000-0000-0000-000000000002")

# Default Surfaces seeded by
# `20260519200000_seed_default_surfaces_and_v2_policy.sql`.
# Default Surfaces. The first three are seeded by
# `20260519200000_seed_default_surfaces_and_v2_policy.sql`;
# `SYSTEM_IN_PROCESS_SURFACE_ID` by a later migration (see
# `cora.infrastructure.schema_version.EXPECTED_SCHEMA_VERSION` for the
# current newest one).
#
# Re-exported above from `cora.infrastructure.routing` so historical
# `from cora.trust._bootstrap import SYSTEM_HTTP_SURFACE_ID` callers
Expand Down Expand Up @@ -242,6 +246,7 @@ async def verify_local_conduit_matches_policy(deps: Kernel) -> None:
__all__ = [
"SYSTEM_BOOTSTRAP_POLICY_ID",
"SYSTEM_HTTP_SURFACE_ID",
"SYSTEM_IN_PROCESS_SURFACE_ID",
"SYSTEM_LOCAL_CONDUIT_ID",
"SYSTEM_MCP_STDIO_SURFACE_ID",
"SYSTEM_MCP_STREAMABLE_HTTP_SURFACE_ID",
Expand Down
11 changes: 11 additions & 0 deletions apps/api/src/cora/trust/aggregates/surface/surface_kind.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@
- MCP_STREAMABLE_HTTP: MCP tool calls arriving over the
streamable-http transport (typical for remote agents). Must
authenticate; audit trail should differentiate from stdio.
- IN_PROCESS: no transport at all. CORA's own background code (agent
runtimes, tick loops, capture readers) calling a handler directly,
in-process, on behalf of no external caller. Distinct from every
other member above, which all name a real wire protocol a request
arrived over; this one names the absence of one. Orthogonal to the
deferred transports below, none of which describe in-process work
either. Not named INTERNAL: that word already names an unrelated
domain value elsewhere (`Operation.acquisitions.trigger_mode`'s
`"Internal"` camera-trigger source), and on its own reads as
"internal network" rather than "no transport."

Deferred kinds (with documented anticipated names so future code
review catches conflicts):
Expand All @@ -40,3 +50,4 @@ class SurfaceKind(StrEnum):
HTTP = "http"
MCP_STDIO = "mcp_stdio"
MCP_STREAMABLE_HTTP = "mcp_streamable_http"
IN_PROCESS = "in_process"
2 changes: 1 addition & 1 deletion apps/api/src/cora/trust/features/define_surface/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class DefineSurfaceRequest(BaseModel):
...,
description=(
"Process-level arrival kind. Closed enum; one of "
"http / mcp_stdio / mcp_streamable_http."
"http / mcp_stdio / mcp_streamable_http / in_process."
),
)

Expand Down
19 changes: 14 additions & 5 deletions apps/api/tests/architecture/test_surface_context_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
)
from cora.infrastructure.routing import (
SYSTEM_HTTP_SURFACE_ID,
SYSTEM_IN_PROCESS_SURFACE_ID,
SYSTEM_MCP_STDIO_SURFACE_ID,
SYSTEM_MCP_STREAMABLE_HTTP_SURFACE_ID,
)
Expand Down Expand Up @@ -142,11 +143,13 @@ def test_bearer_middleware_dispatch_binds_and_clears_surface_context() -> None:
@pytest.mark.architecture
def test_surface_kind_map_covers_all_http_reachable_seeded_surfaces() -> None:
"""`_SURFACE_KIND_BY_UUID` MUST map every HTTP-reachable seeded Surface
UUID to a kind string. `SYSTEM_MCP_STDIO_SURFACE_ID` is intentionally
excluded (stdio is a subprocess transport, never reachable via the
HTTP middleware). A new HTTP-reachable Surface seeded without a kind
entry would cause `surface_kind_for` to raise `UnknownSurfaceError`
at request time; better to catch the gap at architecture-test time.
UUID to a kind string. `SYSTEM_MCP_STDIO_SURFACE_ID` and
`SYSTEM_IN_PROCESS_SURFACE_ID` are intentionally excluded: stdio is a
subprocess transport, and internal is CORA's own in-process work,
neither ever reachable via the HTTP middleware. A new HTTP-reachable
Surface seeded without a kind entry would cause `surface_kind_for` to
raise `UnknownSurfaceError` at request time; better to catch the gap
at architecture-test time.
"""
http_reachable_surfaces = {
SYSTEM_HTTP_SURFACE_ID,
Expand All @@ -166,6 +169,12 @@ def test_surface_kind_map_covers_all_http_reachable_seeded_surfaces() -> None:
"should bind at the FastMCP server entrypoint, not via the "
"HTTP-middleware-bound map."
)
assert SYSTEM_IN_PROCESS_SURFACE_ID not in _SURFACE_KIND_BY_UUID, (
"SYSTEM_IN_PROCESS_SURFACE_ID is in _SURFACE_KIND_BY_UUID; the "
"internal Surface names CORA's own in-process work, which by "
"definition never arrives over the HTTP middleware and so has "
"no arrival kind to bind for observability."
)


@pytest.mark.architecture
Expand Down
Loading
Loading