security: publish hardened v1 initiative snapshot

Publish the reviewed security policy and evidence, exact runtime ABI enforcement, orphan-output and permission safeguards, dead-upstream cleanup, and the evidence-gated v1 launch plan.

This commit is an exact sanitized export from the private development record. Material implementation and review were assisted by OpenAI Codex; Cole Speelman reviewed the changes and accepts human responsibility.

Himesan-Output-Permission: v1.0
Signed-off-by: Cole Speelman <gamertan@noreply.localhost>
This commit is contained in:
2026-08-12 03:54:46 -04:00
parent 4166a66c66
commit 113c95c21e
22 changed files with 1028 additions and 73 deletions
+16
View File
@@ -104,6 +104,22 @@ func (d *developmentProxy) setTarget(address string) error {
return nil
}
// clearTarget forgets address only when it is still the selected upstream.
// The compare-and-swap prevents a concurrently replaced target from being
// cleared between the load and store. The supervisor serializes activation
// and exit handling and calls this only for its current candidate.
func (d *developmentProxy) clearTarget(address string) bool {
target := d.target.Load()
if target == nil || target.Host != address {
return false
}
if !d.target.CompareAndSwap(target, nil) {
return false
}
d.closeIdleConnections()
return true
}
func (d *developmentProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if status, message := d.validateRequest(r); status != 0 {
w.Header().Set("Cache-Control", "no-store")
+20
View File
@@ -250,6 +250,26 @@ func TestWaitingPageConnectsToEvents(t *testing.T) {
}
}
func TestClearTargetOnlyClearsSelectedUpstream(t *testing.T) {
t.Parallel()
proxy := newDevelopmentProxy(newEventHub())
if err := proxy.setTarget("127.0.0.1:7001"); err != nil {
t.Fatal(err)
}
if proxy.clearTarget("127.0.0.1:7002") {
t.Fatal("clearTarget cleared a different selected upstream")
}
if target := proxy.target.Load(); target == nil || target.Host != "127.0.0.1:7001" {
t.Fatalf("selected upstream changed unexpectedly: %v", target)
}
if !proxy.clearTarget("127.0.0.1:7001") {
t.Fatal("clearTarget did not clear the selected upstream")
}
if target := proxy.target.Load(); target != nil {
t.Fatalf("selected upstream remains after clear: %v", target)
}
}
func TestDevelopmentProxyRequiresLocalAuthorityAndSameOrigin(t *testing.T) {
t.Parallel()
var upstreamRequests atomic.Int32
+28 -12
View File
@@ -208,6 +208,7 @@ func (s *Supervisor) Run(ctx context.Context) error {
}()
var current *candidateProcess
var currentExited <-chan struct{}
defer func() {
s.hub.close()
s.proxy.closeIdleConnections()
@@ -224,6 +225,9 @@ func (s *Supervisor) Run(ctx context.Context) error {
s.emit(Event{Type: "ready", Phase: "proxy", Message: "http://" + listener.Addr().String()})
if candidate := s.buildHealthyCandidate(ctx); candidate != nil {
current = s.activateCandidate(candidate, current)
if current != nil {
currentExited = current.exited
}
}
roots := makeWatchRoots(s.rootDir, s.options.Config)
@@ -242,6 +246,25 @@ func (s *Supervisor) Run(ctx context.Context) error {
select {
case <-ctx.Done():
return nil
case <-currentExited:
exited := current
current = nil
currentExited = nil
if exited == nil {
continue
}
// Forget the selected upstream before reporting or cleanup. Future
// requests receive the waiting page and cannot follow a reused port.
s.proxy.clearTarget(exited.address)
exitErr := exited.result()
if exitErr == nil {
exitErr = errors.New("application exited")
} else {
exitErr = fmt.Errorf("application exited: %w", exitErr)
}
_ = exited.cleanupProcessTree()
_ = os.Remove(exited.binaryPath)
s.report("run", exitErr)
case err := <-serverErrors:
if err != nil {
return fmt.Errorf("development proxy: %w", err)
@@ -262,22 +285,15 @@ func (s *Supervisor) Run(ctx context.Context) error {
pending = true
changedAt = now
}
if current != nil && current.hasExited() {
exitErr := current.result()
if exitErr == nil {
exitErr = errors.New("application exited")
} else {
exitErr = fmt.Errorf("application exited: %w", exitErr)
}
s.report("run", exitErr)
_ = current.cleanupProcessTree()
_ = os.Remove(current.binaryPath)
current = nil
}
if pending && now.Sub(changedAt) >= s.options.Debounce {
pending = false
if candidate := s.buildHealthyCandidate(ctx); candidate != nil {
current = s.activateCandidate(candidate, current)
if current != nil {
currentExited = current.exited
} else {
currentExited = nil
}
}
}
}
+99
View File
@@ -96,6 +96,73 @@ func TestSupervisorBuildsSwapsAndCleansUp(t *testing.T) {
waitForConnectionRefused(t, secondUpstream, 3*time.Second)
}
func TestSupervisorClearsTargetWhenCurrentApplicationExits(t *testing.T) {
if testing.Short() {
t.Skip("integration test builds a temporary Go application")
}
root := t.TempDir()
if err := os.WriteFile(filepath.Join(root, "go.mod"), []byte("module example.test/himesan-dev-exit-test\n\ngo 1.25\n"), 0o600); err != nil {
t.Fatal(err)
}
mainPath := filepath.Join(root, "main.go")
writeExitingTestApplication(t, mainPath, "short lived", 1500*time.Millisecond)
cfg := DefaultConfig()
cfg.ProxyAddress = "127.0.0.1:0"
cfg.HealthPath = "/healthz"
events := make(chan Event, 16)
supervisor, err := New(Options{
RootDir: root,
Config: cfg,
Generate: func(context.Context) error { return nil },
OnEvent: func(event Event) { events <- event },
CacheDir: filepath.Join(t.TempDir(), "cache"),
PollInterval: 30 * time.Second,
Debounce: 25 * time.Millisecond,
BuildTimeout: 30 * time.Second,
StartupTimeout: time.Second,
ShutdownTimeout: 2 * time.Second,
})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
runResult := make(chan error, 1)
go func() { runResult <- supervisor.Run(ctx) }()
t.Cleanup(cancel)
proxyAddress := waitForProxyAddress(t, supervisor)
waitForBody(t, "http://"+proxyAddress+"/", "short lived")
waitForPhase(t, events, "run")
if target := supervisor.proxy.target.Load(); target != nil {
t.Fatalf("proxy retained exited upstream %v", target)
}
client := &http.Client{Transport: &http.Transport{Proxy: nil}, Timeout: time.Second}
response, err := client.Get("http://" + proxyAddress + "/")
if err != nil {
t.Fatal(err)
}
body, readErr := io.ReadAll(response.Body)
_ = response.Body.Close()
if readErr != nil {
t.Fatal(readErr)
}
if response.StatusCode != http.StatusServiceUnavailable || !strings.Contains(string(body), "waiting for a healthy application") {
t.Fatalf("dead upstream response = %d %q", response.StatusCode, body)
}
cancel()
select {
case err := <-runResult:
if err != nil {
t.Fatalf("Run() error = %v", err)
}
case <-time.After(5 * time.Second):
t.Fatal("Run() did not stop after cancellation")
}
}
func TestGenerationFailureDoesNotMoveProxyTarget(t *testing.T) {
t.Parallel()
upstream := http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
@@ -173,6 +240,38 @@ func main() {
}
}
func writeExitingTestApplication(t *testing.T, path, message string, lifetime time.Duration) {
t.Helper()
contents := fmt.Sprintf(`package main
import (
"fmt"
"net/http"
"os"
"time"
)
func main() {
go func() {
time.Sleep(%d * time.Millisecond)
os.Exit(0)
}()
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) })
mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, "<!doctype html><html><body>%s</body></html>")
})
if err := http.ListenAndServe(os.Getenv("HIMESAN_LISTEN_ADDR"), mux); err != nil {
panic(err)
}
}
`, lifetime.Milliseconds(), message)
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
t.Fatal(err)
}
}
func waitForPhase(t *testing.T, events <-chan Event, phase string) {
t.Helper()
timer := time.NewTimer(10 * time.Second)