Finish audit remediation and prepare v0.6.0

This commit is contained in:
2026-08-12 13:01:05 +00:00
parent 227fb35f99
commit 4ca3be2c14
10 changed files with 308 additions and 6109 deletions

View File

@@ -1441,6 +1441,29 @@ func TestPromptRepositoryReadFailureMapsToPromptLoad(t *testing.T) {
}
}
func TestPromptDefinitionReadFailureMapsToPromptLoad(t *testing.T) {
readErr := errors.New("definition read failed")
source := &publicDefinitionReadFailureFS{
FS: fstest.MapFS{
"prompts/target.yaml": &fstest.MapFile{Data: []byte("unread")},
},
target: "prompts/target.yaml",
err: readErr,
}
engine, err := promptkit.NewEngine(promptkit.Config{}, promptkit.WithPromptFS(source, "prompts"))
if err != nil {
t.Fatalf("construct engine: %v", err)
}
inspection, err := engine.InspectPrompt(context.Background(), "target", "1")
if inspection != nil || !errors.Is(err, promptkit.ErrPromptLoad) || !errors.Is(err, readErr) {
t.Fatalf("InspectPrompt() = (%#v, %v), want nil with prompt-load and read-error identities", inspection, err)
}
if errors.Is(err, promptkit.ErrPromptNotFound) {
t.Fatalf("definition read error was classified as absence: %v", err)
}
}
func TestSelectedProfileRepositoryReadFailureMapsToProfileLoad(t *testing.T) {
missingProfileDir := filepath.Join(t.TempDir(), "missing-profiles")
engine, err := promptkit.NewEngine(promptkit.Config{
@@ -2696,6 +2719,35 @@ func TestPreparePreservesValidationCancellationIdentity(t *testing.T) {
}
}
func TestPrepareRejectsExcessivelyDeepStructuredOutputSchema(t *testing.T) {
schema, err := json.Marshal(excessivelyDeepStructuredOutputSchema())
if err != nil {
t.Fatalf("marshal schema: %v", err)
}
engine, err := promptkit.NewEngine(promptkit.Config{},
promptkit.WithPromptFS(publicStructuredPromptFS("schema.deep.prompt", "schema.json"), "prompts"),
promptkit.WithSchemaFS(fstest.MapFS{
"schemas/schema.json": &fstest.MapFile{Data: schema},
}, "schemas"),
promptkit.WithProfiles(promptkit.Profile{
ID: "contract-fast", Endpoint: "http://example.test/v1", Model: "schema-model",
}),
)
if err != nil {
t.Fatalf("construct engine: %v", err)
}
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
PromptID: "schema.deep.prompt",
Inputs: map[string]promptkit.ArtifactRef{
"transcript": promptkit.Inline("Rin opens the gate."),
},
})
if prepared != nil || !errors.Is(err, promptkit.ErrValidation) {
t.Fatalf("Prepare() = (%#v, %v), want nil with ErrValidation", prepared, err)
}
}
func TestPreparedStructuredOutputRetainsExactSchemaNumbers(t *testing.T) {
const schema = `{
"type": "number",
@@ -3124,6 +3176,15 @@ func excessivelyDeepJSONValue() any {
return value
}
func excessivelyDeepStructuredOutputSchema() any {
const clearlyUnsafeSchemaNesting = 128
schema := any(map[string]any{"type": "object"})
for level := 0; level < clearlyUnsafeSchemaNesting; level++ {
schema = map[string]any{"allOf": []any{schema}}
}
return schema
}
func excessivelyLargeJSONValue() any {
const clearlyUnsafeSharedOccurrences = 60_000
shared := []any{true}
@@ -3373,6 +3434,19 @@ type countingSchemaFS struct {
reads map[string]int
}
type publicDefinitionReadFailureFS struct {
fs.FS
target string
err error
}
func (f *publicDefinitionReadFailureFS) Open(name string) (fs.File, error) {
if name == f.target {
return nil, f.err
}
return f.FS.Open(name)
}
type cancelingPublicSchemaFS struct {
fs.FS
mu sync.Mutex