From 8de49f2dd3c998b6c66ea70a4d70dc100e8ed58b Mon Sep 17 00:00:00 2001 From: npc0-hue Date: Wed, 2 Sep 2026 12:22:41 +0800 Subject: [PATCH] Keep supervised log entries verbatim --- AGENTS.md | 2 +- protocol/log_ingest.go | 1 - runtime/protected_request_test.go | 3 --- runtime/worker.go | 6 ++---- runtime/worker_test.go | 4 ++-- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5d951cc..6f86581 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ Protocol structs live in `protocol/`. Local runtime types live in `runtime/` or ## Safety Rules -Run must enforce scoped paths and never expose raw host paths, local secrets, or unrestricted command execution to platform_web or plugins. Do not apply game-specific redaction to plugin-declared game records or SQL query rows: return those bounded typed fields faithfully through Platform channels. Supervised stdout/stderr and plugin-declared file tails are opaque verbatim channels: do not inspect, parse, filter, redact, truncate by content, transform, or special-case their payloads. Run only spools and forwards these bytes; a plugin companion may parse its own declared stream and derive its own users or business records after receipt. This pass-through rule does not grant plugins or the browser a direct host-path, credential, key, or socket API outside that log channel. +Run must enforce scoped paths and never expose raw host paths, local secrets, or unrestricted command execution to platform_web or plugins. Do not apply game-specific redaction to plugin-declared game records or SQL query rows: return those bounded typed fields faithfully through Platform channels. Supervised stdout/stderr and plugin-declared file tails are opaque verbatim channels: do not inspect, parse, filter, redact, truncate by content, normalize, correlate, transform, or special-case their payloads. Run only assigns transport metadata, spools, and forwards the exact body bytes. A plugin companion may consume its declared raw stream, parse it, and derive its own typed users or business records after receipt; Run neither performs nor repeats that plugin work. This pass-through rule does not grant plugins or the browser a direct host-path, credential, key, or socket API outside that log channel. ## Generic Executor Boundary diff --git a/protocol/log_ingest.go b/protocol/log_ingest.go index 5d3cf97..e0ab254 100644 --- a/protocol/log_ingest.go +++ b/protocol/log_ingest.go @@ -8,7 +8,6 @@ type LogEntry struct { Level string `json:"level,omitempty"` Line string `json:"line"` Fields map[string]string `json:"fields,omitempty"` - Redacted bool `json:"redacted"` } type LogBatchIngestRequest struct { diff --git a/runtime/protected_request_test.go b/runtime/protected_request_test.go index d185c2c..3e8e497 100644 --- a/runtime/protected_request_test.go +++ b/runtime/protected_request_test.go @@ -63,9 +63,6 @@ func TestWorkerExecutesFencedProtectedProgramAndSpoolsDedicatedLogs(t *testing.T t.Fatalf("program output used wrong log source: %+v", batch) } for _, entry := range batch.Entries { - if entry.Redacted { - t.Fatalf("program log must remain verbatim, got %+v", entry) - } logLines = append(logLines, entry.Line) } } diff --git a/runtime/worker.go b/runtime/worker.go index 3f13e06..0a481f8 100644 --- a/runtime/worker.go +++ b/runtime/worker.go @@ -1404,7 +1404,6 @@ func checksumForLogEntries(entries []protocol.LogEntry) (string, error) { Level: entry.Level, Line: entry.Line, Fields: entry.Fields, - Redacted: entry.Redacted, } } encoded, err := json.Marshal(stable) @@ -1421,7 +1420,6 @@ type logEntryChecksumBody struct { Level string `json:"level,omitempty"` Line string `json:"line"` Fields map[string]string `json:"fields,omitempty"` - Redacted bool `json:"redacted"` } func (worker *Worker) capacityReport() protocol.RunCapacityReport { @@ -1524,7 +1522,7 @@ func (sink *LiveLogSink) append(assignment protocol.RunJobAssignment, stream str FirstSeq: sequence, LastSeq: sequence, Compression: "none", - Entries: []protocol.LogEntry{{Seq: sequence, Timestamp: time.Now().UTC(), Level: "info", Line: line, Redacted: false}}, + Entries: []protocol.LogEntry{{Seq: sequence, Timestamp: time.Now().UTC(), Level: "info", Line: line}}, } batch.Checksum, _ = checksumForLogEntries(batch.Entries) select { @@ -1576,7 +1574,7 @@ func (sink *SpoolLogSink) append(ctx context.Context, assignment protocol.RunJob defer sink.mu.Unlock() streamKey := declaredProcessStreamKey(assignment, stream) logStreamID := logStreamIDForAssignment(assignment, streamKey) - entry := protocol.LogEntry{Timestamp: time.Now().UTC(), Level: "info", Line: line, Redacted: false} + entry := protocol.LogEntry{Timestamp: time.Now().UTC(), Level: "info", Line: line} source := "process" if strings.HasPrefix(stream, "management-program.") { source = "management-program" diff --git a/runtime/worker_test.go b/runtime/worker_test.go index 20fccb6..ca602ca 100644 --- a/runtime/worker_test.go +++ b/runtime/worker_test.go @@ -392,7 +392,7 @@ func TestWorkerSpoolHooksUseRegisteredSession(t *testing.T) { if err != nil { t.Fatalf("pending logs: %v", err) } - if len(logs) != 1 || logs[0].RunEndpointID != "run-test" || logs[0].SessionToken != "session-token" || logs[0].StreamKey != "game.console.stdout" || logs[0].Entries[0].Line != "started password=hidden" || logs[0].Entries[0].Redacted { + if len(logs) != 1 || logs[0].RunEndpointID != "run-test" || logs[0].SessionToken != "session-token" || logs[0].StreamKey != "game.console.stdout" || logs[0].Entries[0].Line != "started password=hidden" { t.Fatalf("unexpected spooled logs: %+v", logs) } chunks, err := artifactQueue.Pending() @@ -623,7 +623,7 @@ func TestSpoolLogSinkKeepsSequencesIndependentAndDurable(t *testing.T) { func TestSessionLogBatchClientOverridesSpooledIdentityAndChecksum(t *testing.T) { recorder := &recordingDurableLogClient{} - entry := protocol.LogEntry{Seq: 7, Timestamp: workerTestTime(), Level: "info", Line: "server ready", Redacted: false} + entry := protocol.LogEntry{Seq: 7, Timestamp: workerTestTime(), Level: "info", Line: "server ready"} batch := protocol.LogBatchIngestRequest{ RunEndpointID: "old-endpoint", SessionToken: "old-token",