Bound external result file reads
This commit is contained in:
@@ -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 {
|
||||
|
||||
19
internal/stage/external_result.go
Normal file
19
internal/stage/external_result.go
Normal 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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user