feat: add store CRUD methods for submission/extraction/finding/evidence
Create/Get for submission (including the one legitimate status transition — submission is not append-only, unlike the other three), Create/GetLatest for extraction and evidence_package, Create for finding plus ListCurrentFindings which applies the anti-join documented in the migration (a finding referenced by another row's `supersedes` is not "current"). Tested against real Postgres, including that the append-only trigger still rejects UPDATE on evidence_package via this new code path, and that ListCurrentFindings actually hides a finding once a correction supersedes it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
56
internal/store/extraction.go
Normal file
56
internal/store/extraction.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Extraction ist das Ergebnis der Stufe-1-Extraktion für einen Beitrag.
|
||||
// Payload ist das rohe, vom Modell gelieferte JSON — nicht eine
|
||||
// abgeleitete Repräsentation. Append-only: siehe Migration.
|
||||
type Extraction struct {
|
||||
ID string
|
||||
SubmissionID string
|
||||
Payload []byte
|
||||
ModelVersion string
|
||||
PromptVersion string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// CreateExtraction speichert eine Extraktion. payload ist das rohe
|
||||
// JSON, wie es das Modell zurückgegeben hat (siehe extract.Result.RawJSON).
|
||||
func (s *Store) CreateExtraction(ctx context.Context, submissionID string, payload []byte, modelVersion, promptVersion string) (Extraction, error) {
|
||||
var e Extraction
|
||||
err := s.Pool.QueryRow(ctx, `
|
||||
INSERT INTO extraction (submission_id, payload, model_version, prompt_version)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, submission_id, payload, model_version, prompt_version, created_at
|
||||
`, submissionID, payload, modelVersion, promptVersion).Scan(
|
||||
&e.ID, &e.SubmissionID, &e.Payload, &e.ModelVersion, &e.PromptVersion, &e.CreatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return Extraction{}, fmt.Errorf("store: create extraction: %w", err)
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// GetLatestExtraction liest die zuletzt erzeugte Extraktion für einen
|
||||
// Beitrag (append-only: es kann mehrere geben, z. B. bei einer erneuten
|
||||
// Prüfung — die aktuellste zählt).
|
||||
func (s *Store) GetLatestExtraction(ctx context.Context, submissionID string) (Extraction, error) {
|
||||
var e Extraction
|
||||
err := s.Pool.QueryRow(ctx, `
|
||||
SELECT id, submission_id, payload, model_version, prompt_version, created_at
|
||||
FROM extraction
|
||||
WHERE submission_id = $1
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
`, submissionID).Scan(
|
||||
&e.ID, &e.SubmissionID, &e.Payload, &e.ModelVersion, &e.PromptVersion, &e.CreatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return Extraction{}, fmt.Errorf("store: get latest extraction: %w", err)
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
Reference in New Issue
Block a user