Skip to content

feat: initial v0.1 scaffold#1

Merged
Taure merged 1 commit into
mainfrom
feat/initial-scaffold
May 19, 2026
Merged

feat: initial v0.1 scaffold#1
Taure merged 1 commit into
mainfrom
feat/initial-scaffold

Conversation

@Taure
Copy link
Copy Markdown
Contributor

@Taure Taure commented May 19, 2026

Summary

Initial v0.1 scaffold of nova_storage — object/file storage abstraction for the Nova ecosystem.

Public API

  • put/4, get/2, get_stream/2, head/2, delete/2, copy/3, exists/2, sign_url/3,4, list/2,3

Adapters

  • nova_storage_local — filesystem with sharded layout, atomic-rename writes, sidecar JSON metadata, partial-write recovery
  • nova_storage_s3 — S3-compatible (AWS / R2 / Scaleway / Minio / B2), httpc + crypto + xmerl, zero new deps

SigV4

Hand-rolled in nova_storage_sigv4 with the documented traps wired in:

  • Year-based clock-skew guard (2020 ≤ year ≤ 2100)
  • UNSIGNED-PAYLOAD rejected on http:// URLs
  • AWS canonical-URI encoding (the feat: initial v0.1 scaffold #1 SigV4 bug)
  • Path-style vs virtual-host addressing exposed in adapter opts
  • Property tests against AWS-published vectors

Telemetry

[nova_storage, Op, start|stop|exception] events for every public operation, with store, adapter, key, result, duration. Optional telemetry dep.

Guardian-flagged design decisions implemented

  1. head/2 and copy/3 added to the behaviour (not just get/put/delete)
  2. ETag documented as adapter-defined, not a content hash
  3. Chunk-fun semantics documented (synchronous, in adapter's process, with timeout)
  4. httpc body-streaming caveat documented + v0.2 gun-based adapter flagged
  5. SigV4 traps handled in code + tests
  6. Local-adapter atomicity sequence implemented (.tmp staging + rename + reap)
  7. One store = one bucket; no multi-bucket-per-store
  8. Telemetry events ship in v0.1
  9. Per-store max_size guard enforced in public API
  10. content_type required on put; no extension sniffing
  11. nova_storage MUST NOT become a dep of nova core (README + CLAUDE.md)

Test plan

  • rebar3 compile — clean
  • rebar3 ct — 16/16 pass
  • rebar3 xref — clean
  • rebar3 dialyzer — clean
  • rebar3 hank — clean
  • rebar3 fmt --check — clean
  • Flip Dependency graph toggle at Settings → Security so CI's dep-submission step passes
  • CI green
  • Release workflow tags v0.1.0

Follow-ups (not in v0.1)

  • nova_storage_s3_gun — true streaming get for large objects
  • PUT signing in sign_url
  • More AWS SigV4 test vectors (get-utf8, post-vanilla, get-vanilla-query-order)
  • GCS / Azure / B2-native adapters

Public API: put/4, get/2, get_stream/2, head/2, delete/2, copy/3, exists/2,
sign_url/3,4, list/2,3. Adapter-owns-its-process model, opaque State, time
in ms, sizes in bytes, one store one bucket. Caller-required content_type;
no extension sniffing. Per-store max_size guard.

Adapters: nova_storage_local (filesystem, sharded layout, atomic rename
writes with .tmp staging + reap on startup) and nova_storage_s3 (any
S3-compatible: AWS / R2 / Scaleway / Minio / B2) using httpc + crypto +
xmerl, no third-party HTTP/sig dependencies.

SigV4 implementation hand-rolled in nova_storage_sigv4 with the documented
traps wired in: year-based clock-skew guard (refuses 2020 > year > 2100),
UNSIGNED-PAYLOAD rejected over HTTP, AWS canonical-URI encoding,
path-style/virtual-host addressing. Property tests against AWS-published
vectors live in test/nova_storage_sigv4_SUITE.erl.

Telemetry: [nova_storage, Op, start|stop|exception] events with store,
adapter, key, result, duration. Optional telemetry dep, no-op when absent.

Ships with Taure/erlang-ci v2 CI + release workflows and ex_doc guides
covering getting-started, adapters, SigV4 internals, and telemetry.
@github-actions
Copy link
Copy Markdown

ℹ️ 15 OTP CVEs auto-ignored (already fixed in running version)

These CVEs are patched in the installed OTP version but NVD data
has not been updated to reflect this. They are excluded from the
scan via an auto-generated .trivyignore.

CVE Details
CVE-2026-32147 Fixed in 28.4.3, running 28.5 — Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') in SFTP chroot
CVE-2026-28808 Fixed in 28.4.2, running 28.5 — ScriptAlias CGI targets bypass directory auth (mod_auth vs mod_cgi path mismatch)
CVE-2026-32144 Fixed in 28.4.2, running 28.5 — OCSP designated-responder authorization bypass — missing signature verification (RFC 6960 §4.2.2.2)
CVE-2026-28810 Fixed in 28.4.2, running 28.5 — Predictable DNS Transaction IDs Enable Cache Poisoning in Built-in Resolver
CVE-2026-23943 Fixed in 28.4.1, running 28.5 — Pre-auth SSH DoS via unbounded zlib inflate
CVE-2026-23942 Fixed in 28.4.1, running 28.5 — SFTP root escape via component-agnostic prefix check in ssh_sftpd
CVE-2026-23941 Fixed in 28.4.1, running 28.5 — Request smuggling via first-wins Content-Length parsing in inets httpd
CVE-2026-21620 Fixed in 28.3.2, running 28.5 — TFTP Path Traversal
CVE-2016-1000107 Fixed in 28.0.4, running 28.5 — Httpd CGI Scripts Environment Variable Pollution AKA "httpoxy"
CVE-2025-58050 Fixed in 28.0.3, running 28.5 — Buffer Read Overflow on Regular Expressions with (*scs:) and (*ACCEPT)
CVE-2025-48038 Fixed in 28.0.3, running 28.5 — SSH Unverified File Handles can Cause Excessive Use of System Resources
CVE-2025-48039 Fixed in 28.0.3, running 28.5 — SSH Unverified Paths can Cause Excessive Use of System Resources
CVE-2025-48040 Fixed in 28.0.3, running 28.5 — SSH Malicious Key Exchange Messages may Lead to Excessive Resource Consumption
CVE-2025-48041 Fixed in 28.0.3, running 28.5 — SSH_FXP_OPENDIR may Lead to Exhaustion of File Handles
CVE-2025-4748 Fixed in 28.0.1, running 28.5 — Absolute Path in Zip Module

@Taure Taure merged commit 395eaff into main May 19, 2026
16 checks passed
@Taure Taure deleted the feat/initial-scaffold branch May 19, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant