Validate execution targets against Nexus instead of accepting free text

Finding 3 of REVIEW-2026-07-30.md. target_entity_id was accepted as any
non-empty string; the engine only compared it against a pinned TargetEntityID,
which is empty for every registered capability. Spec §4.3: "Hexis never
accepts a free-text target. Ever."

Targets are now checked in order: ent_ shape (free, never touches the
network), pinned target, existence in Nexus, entity still active, and a match
against the capability's TargetTypes. Validation runs before a confirmation is
consumed, so a bad target cannot burn one, and at confirmation-mint time too,
since a confirmation binds a target.

Two deliberate calls:

Nexus unreachable fails closed (503, ErrTargetUnverifiable). Failing open
would reinstate exactly this hole the moment Nexus blips, and hand it to
anyone able to degrade Nexus. Hexis holds no entity table, so "unreachable"
and "I cannot tell if this target is real" are the same statement. The cost is
that executes now require Nexus liveness; the lookup is bounded at 5s so a
hung Nexus fails fast rather than consuming the capability timeout.

An empty TargetTypes means no type constraint, not a bypass — the entity must
still exist, be canonical and be active. Rejecting empty outright would
disable 16 of the 19 registered capabilities, since only the docker.* entries
declare a target type.

The spec's stronger blessing guard is not implementable: Nexus has no blessing
concept at all. This is the achievable guard, and strictly weaker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uea55zaiWuEByEDC4UBSdd
This commit is contained in:
kami
2026-07-30 23:39:40 +04:00
parent d4285607af
commit 47be24c4cc
6 changed files with 476 additions and 22 deletions
+12 -1
View File
@@ -278,8 +278,19 @@ func executeErrorStatus(err error) int {
switch {
case errors.Is(err, domain.ErrExecutionInFlight):
return http.StatusConflict
case errors.Is(err, domain.ErrCapabilityNotFound):
case errors.Is(err, domain.ErrCapabilityNotFound),
errors.Is(err, execution.ErrTargetNotFound):
return http.StatusNotFound
case errors.Is(err, execution.ErrTargetMalformed):
return http.StatusBadRequest
case errors.Is(err, execution.ErrTargetTypeMismatch),
errors.Is(err, execution.ErrTargetNotActive):
return http.StatusUnprocessableEntity
// Nexus is the only authority on whether a target is real. If it cannot
// be reached we refuse the execution rather than accepting the target on
// trust — 503, because retrying later is the correct client behaviour.
case errors.Is(err, execution.ErrTargetUnverifiable):
return http.StatusServiceUnavailable
case errors.Is(err, domain.ErrConfirmationRequired),
errors.Is(err, domain.ErrConfirmationInvalid),
errors.Is(err, domain.ErrConfirmationExpired),