feat(assets): add native Go asset/file loader for migrate-apply (#7) #8

Merged
warkanum merged 1 commits from issue-7-native-asset-loader into master 2026-07-18 20:35:46 +00:00
Member

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

  • YAML manifest (assets.yaml) colocated with asset files describes each entry: source file path, SQL call with :bytes/:filename/:param named placeholders, and an optional static params map.
  • Byte-exact binary transfer — file content is bound as []byte via pgx, so binary files (images, docx, etc.) pass through untouched with no base64/escaping round-trip.
  • Ordering convention — manifests must reside in directories following the {priority}_{sequence}_{name} pattern already used by relspec scripts, so asset-loading steps can be correctly interleaved with SQL scripts in a migrate-apply pipeline.
  • Security — symlink components and path traversal (../) are silently skipped to prevent directory escape.
  • PostgreSQL cast protection::type cast syntax is temporarily masked before placeholder substitution so ::text is never misread as a placeholder.

New commands

relspec assets list   --dir <path>
relspec assets execute --dir <path> --conn <postgres-dsn> [--ignore-errors]

Tests

14 unit tests covering:

  • Manifest loading (valid, static params, missing file, invalid YAML)
  • Directory scanning and ordering (priority → sequence → dir name)
  • Symlink skipping and path-traversal rejection
  • Placeholder substitution (basic, static params, repeated, ::cast protection, unknown, binary byte-exact)

Run: go test ./pkg/assetloader/... -v -race

Verification

make build      # → build/relspec (no errors)
make test       # → all tests pass, no FAIL lines
go test ./pkg/assetloader/... -v -race   # → 14/14 PASS
## 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 - **YAML manifest** (`assets.yaml`) colocated with asset files describes each entry: source file path, SQL call with `:bytes`/`:filename`/`:param` named placeholders, and an optional static `params` map. - **Byte-exact binary transfer** — file content is bound as `[]byte` via pgx, so binary files (images, docx, etc.) pass through untouched with no base64/escaping round-trip. - **Ordering convention** — manifests must reside in directories following the `{priority}_{sequence}_{name}` pattern already used by `relspec scripts`, so asset-loading steps can be correctly interleaved with SQL scripts in a `migrate-apply` pipeline. - **Security** — symlink components and path traversal (`../`) are silently skipped to prevent directory escape. - **PostgreSQL cast protection** — `::type` cast syntax is temporarily masked before placeholder substitution so `::text` is never misread as a placeholder. ## New commands ``` relspec assets list --dir <path> relspec assets execute --dir <path> --conn <postgres-dsn> [--ignore-errors] ``` ## Tests 14 unit tests covering: - Manifest loading (valid, static params, missing file, invalid YAML) - Directory scanning and ordering (priority → sequence → dir name) - Symlink skipping and path-traversal rejection - Placeholder substitution (basic, static params, repeated, `::cast` protection, unknown, binary byte-exact) Run: `go test ./pkg/assetloader/... -v -race` ## Verification ```bash make build # → build/relspec (no errors) make test # → all tests pass, no FAIL lines go test ./pkg/assetloader/... -v -race # → 14/14 PASS ```
sgcommand added 1 commit 2026-07-17 00:46:00 +00:00
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>
warkanum merged commit 2aecd1312e into master 2026-07-18 20:35:45 +00:00
Owner

Merged

Merged
warkanum deleted branch issue-7-native-asset-loader 2026-07-18 20:35:58 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wdevs/relspecgo#8