Initial commit: Hexis capability registry + execution service baseline

Go daemon (hexisd/hexisctl) implementing capability registry, guarded
execution (confirmations, blessed-entity checks), systemd/workspace-mcp
providers per ECOSYSTEM-SPEC.md. Snapshotting existing working state
before further development.
This commit is contained in:
kami
2026-07-20 00:50:37 +04:00
commit cca63269e1
20 changed files with 2461 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
package domain
import "time"
type ExecuteRequest struct {
CapabilityID string `json:"capability_id"`
TargetEntityID string `json:"target_entity_id"`
EntityVersion int64 `json:"entity_version,omitempty"`
Arguments map[string]any `json:"arguments,omitempty"`
RequestedBy map[string]string `json:"requested_by,omitempty"`
Origin map[string]string `json:"origin,omitempty"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
CorrelationID string `json:"correlation_id,omitempty"`
ResolutionEvidence []map[string]any `json:"resolution_evidence,omitempty"`
}
type Capability struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
TargetTypes []string `json:"target_types"`
TargetEntityID string `json:"target_entity_id,omitempty"`
Provider string `json:"provider"`
Operation string `json:"operation"`
Risk string `json:"risk,omitempty"`
ReadOnly bool `json:"read_only"`
ExpectedSideEffects string `json:"expected_side_effects,omitempty"`
Attributes map[string]any `json:"attributes,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Version int64 `json:"version"`
}
type ExecutionStatus string
const (
ExecutionStarted ExecutionStatus = "started"
ExecutionSucceeded ExecutionStatus = "succeeded"
ExecutionFailed ExecutionStatus = "failed"
ExecutionDenied ExecutionStatus = "denied"
)
type Execution struct {
ID string `json:"id"`
CapabilityID string `json:"capability_id"`
TargetEntityID string `json:"target_entity_id"`
EntityVersion int64 `json:"entity_version,omitempty"`
Arguments map[string]any `json:"arguments,omitempty"`
RequestedBy map[string]string `json:"requested_by,omitempty"`
Origin map[string]string `json:"origin,omitempty"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
Status ExecutionStatus `json:"status"`
Result map[string]any `json:"result,omitempty"`
Error string `json:"error,omitempty"`
ResolutionEvidence []map[string]any `json:"resolution_evidence,omitempty"`
CorrelationID string `json:"correlation_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type HexisEventType string
const (
EventCapabilityRegistered HexisEventType = "hexis.capability.registered"
EventCapabilityUnavailable HexisEventType = "hexis.capability.unavailable"
EventExecutionStarted HexisEventType = "hexis.execution.started"
EventExecutionSucceeded HexisEventType = "hexis.execution.succeeded"
EventExecutionFailed HexisEventType = "hexis.execution.failed"
EventExecutionDenied HexisEventType = "hexis.execution.denied"
)
type Event struct {
ID string `json:"id"`
Sequence int64 `json:"sequence"`
Type HexisEventType `json:"type"`
Timestamp time.Time `json:"timestamp"`
Actor string `json:"actor,omitempty"`
CorrelationID string `json:"correlation_id,omitempty"`
CausationID string `json:"causation_id,omitempty"`
Payload map[string]any `json:"payload,omitempty"`
}
+18
View File
@@ -0,0 +1,18 @@
package domain
import "errors"
var (
ErrCapabilityNotFound = errors.New("capability not found")
ErrExecutionNotFound = errors.New("execution not found")
ErrConflict = errors.New("version conflict")
ErrAmbiguousTarget = errors.New("ambiguous target")
ErrTargetNotFound = errors.New("target not found")
ErrTargetTypeMismatch = errors.New("target type does not match capability")
ErrCapabilityNotBound = errors.New("capability not registered for this entity")
ErrEntityRetired = errors.New("entity is retired")
ErrEntityMerged = errors.New("entity is merged")
ErrValidation = errors.New("validation error")
ErrInternal = errors.New("internal error")
ErrIdempotencyReplay = errors.New("idempotent request already processed")
)
+25
View File
@@ -0,0 +1,25 @@
package domain
import (
"crypto/rand"
"encoding/base32"
"strings"
)
func NewCapabilityID() string {
b := make([]byte, 10)
rand.Read(b)
return "cap_" + strings.ToLower(base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(b))
}
func NewExecutionID() string {
b := make([]byte, 14)
rand.Read(b)
return "exec_" + strings.ToLower(base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(b))
}
func NewEventID() string {
b := make([]byte, 10)
rand.Read(b)
return "hevt_" + strings.ToLower(base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(b))
}