ts/CLAUDE.md
Snider 66e2df79b6 fix(ts): update stale API call and apply gofmt formatting
- Fix marketplace.NewInstaller call to match go-scm v0.3.4 signature
  (now requires Medium as first argument)
- Apply gofmt: sort imports lexicographically, fix struct field alignment
- Update CLAUDE.md: correct DenoClient mutex type (sync.Mutex not RWMutex)
- Remove stale pkg/coredeno comment and unnecessary unused import guard

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 09:13:40 +00:00

80 lines
4.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
CoreTS (`forge.lthn.ai/core/ts`) is a Go package that manages a Deno 2.x TypeScript runtime as a sandboxed sidecar process. It provides bidirectional communication between Go and Deno over Unix sockets using gRPC (Go→Deno calls) and JSON-RPC (Deno→Go calls), with fine-grained permission gating for filesystem, key-value store, and process operations.
This is a **library package** — no standalone binary. It compiles as part of applications that import it.
## Build & Test Commands
```bash
go build ./... # Build
go test ./... # Unit tests (no Deno needed)
go test -tags integration -timeout 60s ./... # Integration tests (requires Deno 2.x)
go test -run TestName ./... # Single test
go test -race ./... # Race detector
go test -cover ./... # Coverage
go fmt ./... # Format
go vet ./... # Vet
# Proto regeneration
protoc --go_out=. --go-grpc_out=. proto/coredeno.proto
```
## Architecture
All Go code lives in a single `ts` package (no subpackages).
**Two communication channels over Unix sockets:**
- **CoreService (gRPC)** — Go implements, Deno calls. Handles: FileRead/Write/List/Delete, StoreGet/Set, ProcessStart/Stop. Every call is permission-gated against the module's manifest.
- **DenoService (JSON-RPC)** — Deno implements, Go calls. Handles: LoadModule, UnloadModule, ModuleStatus. Newline-delimited JSON over raw Unix socket.
**Startup sequence:** Create sandboxed Medium → Open SQLite store → Start gRPC listener on Unix socket → Launch Deno sidecar (passes CORE_SOCKET/DENO_SOCKET env vars) → Connect DenoClient → Auto-load installed modules.
**Module isolation:** Each module runs in a Deno Worker. The I/O bridge pattern is: module calls core API → worker-entry intercepts via postMessage RPC → ModuleRegistry relays to CoreClient gRPC → Go Server checks permissions with injected module code → result returns through same chain.
### Key Go types
- `Options` — Configuration (DenoPath, SocketPath, AppRoot, etc.)
- `Sidecar` — Manages Deno child process lifecycle
- `Server` — CoreService gRPC implementation with permission gating
- `DenoClient` — JSON-RPC client for module lifecycle
- `Service` — Framework integration (Startable/Stoppable lifecycle)
### Key TypeScript files (runtime/)
- `main.ts` — Entry point, boots gRPC client + JSON-RPC server
- `modules.ts` — ModuleRegistry, Worker lifecycle management
- `client.ts` — CoreService gRPC client wrapper
- `server.ts` — DenoService JSON-RPC server
- `worker-entry.ts` — Worker bootstrap, I/O bridge to parent
- `polyfill.ts` — Deno 2.x http2/grpc-js compatibility fixes (must import before @grpc/grpc-js)
## Code Conventions
- **UK English** in docs and comments (colour, organisation)
- **Error wrapping:** `fmt.Errorf("coredeno: <context>: %w", err)`
- **Test naming:** `_Good`, `_Bad`, `_Ugly` suffixes for test functions
- **Thread safety:** `Sidecar` uses `sync.RWMutex`; `DenoClient` uses `sync.Mutex`
- **Security model:** Empty permission lists deny all access; reserved store namespaces (prefixed `_`) blocked from modules; path matching uses boundary checks to prevent `"data"` matching `"data-secrets"`
## Testing
- **Unit tests** run without Deno — use `MockMedium` and `mockProcessRunner`
- **Integration tests** require `//go:build integration` tag and Deno 2.x installed; tests skip gracefully via `findDeno()` if Deno is absent
- Integration tests are tiered: Tier 1 (boot), Tier 2 (bidirectional comms), Tier 3 (Worker isolation + I/O bridge), Tier 4 (marketplace install)
## Dependencies
- `forge.lthn.ai/core/go` — Core framework (DI, ServiceRuntime)
- `forge.lthn.ai/core/go-io` — Sandboxed filesystem Medium
- `forge.lthn.ai/core/go-io/store` — SQLite key-value store
- `forge.lthn.ai/core/go-scm` — Manifest loading + marketplace installer
- `google.golang.org/grpc` — gRPC transport
- Deno side uses `@grpc/grpc-js` and `@grpc/proto-loader` (npm imports via deno.json, no codegen needed)
## Proto
Source: `proto/coredeno.proto` defines both `CoreService` and `DenoService`. Go stubs are generated; Deno loads the `.proto` dynamically at runtime via `@grpc/proto-loader`.