feat(toolintent): activate per-session egress allowlist (D)
ToolCallAssessmentInput gains sessionEgressHosts; SessionOrchestrator resolves it at
the assessment build site by folding EgressHostsGrantedEvents through
EgressAllowlistProjection. NetworkHostRule now enforces session-granted hosts (union
with static), replacing the emptySet() TODO — the allowlist built in 027ff1f is live.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+17
@@ -76,6 +76,7 @@ import com.correx.core.events.events.WorkflowCompletedEvent
|
||||
import com.correx.core.events.events.WorkflowFailedEvent
|
||||
import com.correx.core.events.events.WorkflowStartedEvent
|
||||
import com.correx.core.events.stores.EventStore
|
||||
import com.correx.core.sessions.projections.EgressAllowlistProjection
|
||||
import com.correx.core.events.types.ApprovalDecisionId
|
||||
import com.correx.core.events.types.ApprovalRequestId
|
||||
import com.correx.core.events.types.ArtifactId
|
||||
@@ -939,6 +940,10 @@ abstract class SessionOrchestrator(
|
||||
): RiskSummary? {
|
||||
val assessor = toolCallAssessor ?: return null
|
||||
val policy = effectives.policy ?: return null
|
||||
// Resolve the egress hosts granted to this session by folding its EgressHostsGrantedEvents
|
||||
// through the projection. Unioned with the static allow-list in NetworkHostRule; empty when
|
||||
// nothing has been granted, which never narrows the static allow-list.
|
||||
val sessionEgressHosts = resolveSessionEgressHosts(sessionId)
|
||||
val assessment = assessor.assess(
|
||||
ToolCallAssessmentInput(
|
||||
request = request,
|
||||
@@ -947,6 +952,7 @@ abstract class SessionOrchestrator(
|
||||
probe = worldProbe,
|
||||
paramRoles = tool?.paramRoles ?: emptyMap(),
|
||||
writeManifest = writeManifest,
|
||||
sessionEgressHosts = sessionEgressHosts,
|
||||
),
|
||||
)
|
||||
emit(
|
||||
@@ -965,6 +971,17 @@ abstract class SessionOrchestrator(
|
||||
return assessment.toRiskSummary()
|
||||
}
|
||||
|
||||
/**
|
||||
* Folds this session's [com.correx.core.events.events.EgressHostsGrantedEvent]s through
|
||||
* [EgressAllowlistProjection] into the running union of hosts granted to it. Replay-safe (reads
|
||||
* the log, never live state); empty when no grants have been emitted.
|
||||
*/
|
||||
internal fun resolveSessionEgressHosts(sessionId: SessionId): Set<String> {
|
||||
val projection = EgressAllowlistProjection(sessionId)
|
||||
return eventStore.read(sessionId)
|
||||
.fold(projection.initial()) { acc, event -> projection.apply(acc, event) }
|
||||
}
|
||||
|
||||
private suspend fun buildSchemaEntries(
|
||||
responseFormat: ResponseFormat,
|
||||
stageId: StageId,
|
||||
|
||||
Reference in New Issue
Block a user