feat(assets): add native Go asset/file loader for migrate-apply (#7) #8
Reference in New Issue
Block a user
Delete Branch "issue-7-native-asset-loader"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements a native Go asset loader (
relspec assets) that loads local binary and text files into PostgreSQL by binding file bytes as native pgx query parameters — never as SQL text literals.Closes #7.
Key design points
assets.yaml) colocated with asset files describes each entry: source file path, SQL call with:bytes/:filename/:paramnamed placeholders, and an optional staticparamsmap.[]bytevia pgx, so binary files (images, docx, etc.) pass through untouched with no base64/escaping round-trip.{priority}_{sequence}_{name}pattern already used byrelspec scripts, so asset-loading steps can be correctly interleaved with SQL scripts in amigrate-applypipeline.../) are silently skipped to prevent directory escape.::typecast syntax is temporarily masked before placeholder substitution so::textis never misread as a placeholder.New commands
Tests
14 unit tests covering:
::castprotection, unknown, binary byte-exact)Run:
go test ./pkg/assetloader/... -v -raceVerification
Implements a new `relspec assets` command (list/execute subcommands) that loads local binary and text asset files into PostgreSQL by binding file bytes as native pgx query parameters — never as SQL text literals — so binary data stays byte-exact with no escaping overhead. Key design points: - YAML manifest (assets.yaml) colocated with files describes each entry: file path, SQL call with :bytes/:filename/:param named placeholders, and optional static params map. - Placeholder substitution converts :name to positional $N params; PostgreSQL ::cast syntax is protected before substitution to avoid false matches. - Directory scan follows the existing {priority}_{sequence}_{name} naming convention, enabling asset-loading steps to be correctly interleaved with relspec scripts execute in a migrate-apply pipeline. - Symlink components and path traversal (../) are silently skipped to prevent directory escape attacks. - 14 unit tests cover manifest loading, directory scanning, ordering, symlink skipping, path traversal rejection, placeholder substitution edge cases (repeated, cast protection, binary byte-exact, unknown). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>Merged