Bound external result file reads

This commit is contained in:
2026-08-10 18:30:28 +00:00
parent 99b2e1cd81
commit ab5a7e8e3d
22 changed files with 215 additions and 84 deletions

View File

@@ -916,14 +916,11 @@ func deriveSessionVarValue(name string, session *config.SessionConfig) (string,
}
func requireNonEmptyFile(path string, label string) error {
if err := requireFile(path, label); err != nil {
data, err := readExternalResult(path, label)
if err != nil {
return err
}
info, err := os.Stat(path)
if err != nil {
return fmt.Errorf("%s %q stat failed: %w", label, path, err)
}
if info.Size() <= 0 {
if len(data) == 0 {
return fmt.Errorf("%s %q is empty", label, path)
}
return nil
@@ -968,9 +965,9 @@ func resolveRenderDebugEnabled(global bool, perArtifact *bool) bool {
}
func validateJSONFile(path string) error {
data, err := os.ReadFile(path)
data, err := readExternalResult(path, "scriptorium artifact result")
if err != nil {
return fmt.Errorf("read file: %w", err)
return err
}
var payload any
if err := json.Unmarshal(data, &payload); err != nil {

View File

@@ -0,0 +1,19 @@
package stage
import (
"fmt"
"gitea.maximumdirect.net/eric/narratio/internal/fileops"
)
// MaxExternalResultFileBytes bounds transcript and artifact files produced by
// external adapters before a stage validates or materializes them.
const MaxExternalResultFileBytes int64 = 64 * 1024 * 1024
func readExternalResult(path, category string) ([]byte, error) {
data, err := fileops.ReadRegularFile(path, MaxExternalResultFileBytes)
if err != nil {
return nil, fmt.Errorf("%s exceeds or cannot be read within %d-byte limit: %w", category, MaxExternalResultFileBytes, err)
}
return data, nil
}

View File

@@ -349,9 +349,9 @@ func checksumRegularFile(path string, requireJSON bool) (string, error) {
if info.Size() == 0 {
return "", fmt.Errorf("path %q must be non-empty", path)
}
data, err := os.ReadFile(path)
data, err := fileops.ReadRegularFile(path, artifacts.MaxExtractionPayloadBytes)
if err != nil {
return "", err
return "", fmt.Errorf("notarius lane result exceeds or cannot be read within %d-byte limit: %w", artifacts.MaxExtractionPayloadBytes, err)
}
if requireJSON && !json.Valid(data) {
return "", fmt.Errorf("path %q is not valid JSON", path)

View File

@@ -284,9 +284,9 @@ func validateProcessedTranscriptOutput(path string) error {
if err := requireFile(path, "processed transcript"); err != nil {
return err
}
data, err := os.ReadFile(path)
data, err := readExternalResult(path, "audita processed transcript result")
if err != nil {
return fmt.Errorf("read processed transcript: %w", err)
return err
}
var payload map[string]any

View File

@@ -2,7 +2,6 @@ package stage
import (
"fmt"
"os"
"path/filepath"
"strings"
@@ -130,9 +129,9 @@ func materializeRunLocalOutput(
if canonicalPath == "" {
return artifacts.Ref{}, fmt.Errorf("canonical destination path is required")
}
data, err := os.ReadFile(srcPath)
data, err := readExternalResult(srcPath, "run-local external output")
if err != nil {
return artifacts.Ref{}, fmt.Errorf("read run-local output %q: %w", srcPath, err)
return artifacts.Ref{}, err
}
if err := store.WriteFileAtomic(canonicalPath, data, fileops.WorkspaceFileMode); err != nil {
return artifacts.Ref{}, fmt.Errorf("materialize output to %q: %w", canonicalPath, err)

View File

@@ -321,9 +321,9 @@ func validateTranscriptJSONFile(path string) error {
if err := requireFile(path, "raw transcript"); err != nil {
return err
}
data, err := os.ReadFile(path)
data, err := readExternalResult(path, "whisperx transcript result")
if err != nil {
return fmt.Errorf("read transcript: %w", err)
return err
}
var payload any
if err := json.Unmarshal(data, &payload); err != nil {

View File

@@ -3,7 +3,6 @@ package stage
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"time"
@@ -389,9 +388,9 @@ func resolveTrimmedOutputPath(paths artifacts.SessionPaths, cfg *config.TrimConf
}
func copyTranscript(store artifacts.Store, src, dst string) error {
data, err := os.ReadFile(src)
data, err := readExternalResult(src, "seriatim trimmed transcript result")
if err != nil {
return fmt.Errorf("read source transcript: %w", err)
return err
}
if err := store.WriteFileAtomic(dst, data, fileops.WorkspaceFileMode); err != nil {
return fmt.Errorf("write destination transcript: %w", err)