CoreTS
Module: forge.lthn.ai/core/ts
Go service that manages a Deno TypeScript runtime as a sidecar process. Provides bidirectional communication between Go and Deno via Unix socket gRPC and JSON-RPC, sandboxed filesystem access, permission-gated module loading, and marketplace module installation. Integrates with the Core framework as a Startable/Stoppable service.
Architecture
The startup sequence is: sandboxed Medium -> SQLite Store -> gRPC Server -> manifest load/verify -> gRPC listener -> Deno sidecar -> DenoClient connection -> marketplace module auto-load.
Go exposes a gRPC CoreService server on a Unix socket. Deno exposes a JSON-RPC DenoService server on a separate socket. The DenoClient connects to Deno's socket and sends module lifecycle commands.
Key Types
Options
type Options struct {
DenoPath string // path to deno binary (default: "deno")
SocketPath string // Unix socket for Go's gRPC server
DenoSocketPath string // Unix socket for Deno's JSON-RPC server
AppRoot string // sandboxed I/O root directory
StoreDBPath string // SQLite DB path (default: AppRoot/.core/store.db)
PublicKey ed25519.PublicKey // ed25519 key for manifest verification (optional)
SidecarArgs []string // args passed to the sidecar process
}
Sidecar
Manages the Deno child process. Thread-safe via RWMutex.
type Sidecar struct { opts Options; cmd *exec.Cmd; ctx context.Context; cancel context.CancelFunc; done chan struct{} }
NewSidecar(opts) *Sidecar— creates sidecar with defaults (deno path, socket paths, store path).Start(ctx, args...) error— launches Deno process.Stop() error— terminates Deno process.
DenoClient
JSON-RPC client over Unix socket. Thread-safe (mutex-serialised requests).
type DenoClient struct { conn net.Conn; reader *bufio.Reader }
DialDeno(socketPath) (*DenoClient, error)— connect to Deno's server.LoadModule(code, entryPoint, perms) (*LoadModuleResponse, error)— load module with permissions.UnloadModule(code) (*UnloadModuleResponse, error)— unload module.ModuleStatus(code) (*ModuleStatusResponse, error)— query module status.
ModulePermissions
Per-module Deno Worker sandbox permissions:
type ModulePermissions struct {
Read []string // filesystem read paths
Write []string // filesystem write paths
Net []string // network host:port pairs
Run []string // executable commands
}
Permissions (standalone)
type Permissions struct { Read, Write, Net, Run []string }
Flags() []string— converts to Deno--allow-*CLI flags.
Validation functions:
CheckPath(path, allowed) bool— validates path against allowed prefixes (prevents traversal).CheckNet(addr, allowed) bool— validates network address.CheckRun(cmd, allowed) bool— validates command.
Service
Core framework service wrapping the full CoreDeno subsystem.
type Service struct {
*core.ServiceRuntime[Options]
sidecar *Sidecar
grpcServer *Server
store *store.Store
denoClient *DenoClient
installer *marketplace.Installer
}
NewServiceFactory(opts) func(*core.Core) (any, error)— factory forcore.WithService().OnStartup(ctx) error— boots medium, store, gRPC, manifest, sidecar, client, installer.OnShutdown(ctx) error— tears down in reverse order.- Accessors:
Sidecar(),GRPCServer(),DenoClient(),Installer().
Server
gRPC server implementing the CoreService protobuf definition. Handles file I/O, store operations, and module registration for Deno.
Dependencies
Direct: go-io, testify, grpc, protobuf.
Indirect: go-log, go-scm/manifest, go-scm/marketplace, go-io/store.
Usage
svc := ts.NewServiceFactory(ts.Options{
AppRoot: "/path/to/app",
SidecarArgs: []string{"run", "--unstable", "main.ts"},
})
core.New(core.WithService(svc))