Skip to content

Releases: kserksi/summeRain

v2.0.4

v2.0.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 Jul 07:25

v2.0.4 - Supervised Worker Shutdown

Development prerelease. This release is published from dev, may receive
rapid follow-up changes, and is not selected by the default latest image.

Summary

v2.0.4 gives every worker owned by the backend worker manager a common
supervisor and a coordinated, bounded shutdown path. A worker that panics or
returns unexpectedly is restarted with exponential backoff, while an intended
drain stops new claims, completes bounded cleanup, and never starts replacement
work.

Shutdown now drains request-producing HTTP traffic before worker consumers.
The process first becomes unready, then allows active HTTP requests to finish,
drains workers, applies a hard cancellation when required, and finally closes
Redis and MySQL resources. Listener failures enter the same lifecycle as
SIGINT and SIGTERM instead of terminating through log.Fatalf.

This release does not add a database schema version, change an HTTP or upload
API, or change an image-processing recipe.

Changes

Unified worker supervision

  • Runs heartbeat, outbox, V2 publish, V2 cleanup, view flush, cleanup, and user
    deletion workers under one named supervisor.
  • Recovers worker panics and restarts unexpected returns with bounded
    exponential delays of 1, 2, 4, 8, 16, and 30 seconds. Further failures remain
    capped at 30 seconds.
  • Logs the failed worker name and original panic value so repeated failures can
    be attributed without terminating the entire process.
  • Keeps Manager.Start(ctx) blocking until all supervised workers stop and
    exposes an idempotent, concurrency-safe BeginDrain() signal.
  • Interrupts restart waits immediately when either drain or hard cancellation
    begins, and never restarts a worker after either stop signal.

Producer-before-consumer shutdown

  • Changes /ready to return HTTP 503 with status: draining as soon as
    shutdown begins. /health behavior is unchanged.
  • Drains the HTTP server before asking workers to stop claiming work. This lets
    in-flight uploads finish creating their durable publish and outbox records
    before the consumers perform their final drain.
  • Waits for workers during a soft-drain phase, then cancels their root context
    and waits through a separate hard-stop phase when needed.
  • Closes Redis and the SQL pool only after worker completion or expiry of the
    worker stop budget.
  • Routes unexpected listener exit through the same shutdown coordinator and
    reports shutdown failures without using a fatal logger in the lifecycle path.

Bounded lifecycle budget

  • Enforces a 30-second application shutdown budget: up to 18 seconds for HTTP
    drain, 5 seconds for worker soft drain, 5 seconds for worker hard stop, and
    2 seconds for runtime resource closure.
  • Increases the Compose backend stop_grace_period to 40 seconds, leaving time
    for the 30-second application budget and container runtime scheduling.
  • Bounds final view flushing and lease cleanup with fresh contexts so cleanup
    can still run after the normal worker context has been canceled.

Durable publish and outbox leases

  • Stops V2 publish and outbox workers from claiming new rows after drain begins
    while allowing the currently claimed operation to finish during soft drain.
  • Releases interrupted publish and outbox claims with a fresh three-second
    cleanup context.
  • Fences every release by lease owner and lease token. Cleanup from an old
    worker cannot clear a completed row or a lease acquired by a replacement.
  • Refunds the claim attempt for orderly cancellation so shutdown alone does not
    consume the retry budget.
  • Preserves the attempt for a publish panic, then rethrows the panic to the
    supervisor so deterministic failures can still reach the attempt limit.
  • On an outbox delivery panic, marks only the active event failed, refunds
    untouched claimed events, and rethrows the original panic to the supervisor.

Final view-count flush

  • Performs one final view-count flush with a fresh context bounded at three
    seconds on either soft drain or hard cancellation.
  • When an explicit MySQL update error follows Redis GETDEL, restores the
    removed count with a fresh one-second Redis INCRBY context instead of
    silently dropping it.
  • Keeps the restore operation inside the five-second worker hard-stop budget.

Continuous integration

  • Adds a dedicated lifecycle schema to the pinned MySQL 8.4.10 CI service.
  • Adds required real-MySQL coverage for publish lease owner/token fencing,
    publish panic release and propagation, and outbox lease owner/token fencing.
  • Adds supervisor, restart-backoff, drain ordering, lifecycle deadline,
    readiness-gate, view-flush, and Compose grace-period unit tests.

Verification

  • Real MySQL 8.4 lifecycle schema bootstrap and three lease-cleanup integration
    scenarios: passed.
  • Backend go test ./... -count=1: passed.
  • Backend race tests for server lifecycle, workers, and publish service: passed.
  • Backend go vet ./...: passed.
  • Backend go build ./...: passed.
  • Frontend ESLint, Vitest, TypeScript project, and Vite production build: passed.
  • Python requirements lock and release-image policy tests: passed.
  • GitBook documentation and translation verification: passed after refreshing
    translation source hashes for this release.
  • The existing wasm-vips direct-eval dependency warning remains unchanged and
    does not fail the build.

Installation

Development images must be pulled explicitly:

docker pull jaykserks/summerain:dev-v2.0.4

Equivalent exact development tag:

jaykserks/summerain:dev-2.0.4

The moving dev tag also points to the newest successful development build.
latest, main, and stable semantic-version aliases are not changed by this
release.

No database migration or API migration is required when upgrading from
v2.0.3. A rolling upgrade is supported, but production operators should pin an
exact image tag or digest rather than the moving dev tag.

Known Limitations

  • View counts still cross Redis and MySQL without a transactional or idempotent
    ledger. If MySQL commits an update but returns an uncertain error, restoring
    the Redis count can apply that count a second time during a later flush. The
    new restore path prevents loss for explicit failures; it does not provide
    cross-store exactly-once delivery.
  • Heartbeat and user-deletion workers stop between batches, but every database
    operation inside an already running batch is not yet fully context-aware. An
    in-flight database call can therefore remain until its driver operation
    returns or the process stop deadline is enforced.
  • Strict configuration parsing and validation remain planned for v2.0.5.
  • The supervisor covers only background workers owned by Manager. Resource-
    intensive paths executed inside requests, including legacy V1 AVIF
    conversion, are not managed by this supervisor. Their resource admission and
    limiting controls remain planned for v2.0.6.
  • Complete readiness checks for runtime dependencies and worker health remain
    planned for v2.0.7. v2.0.4 only makes readiness fail immediately during
    shutdown drain.
  • Animated image support remains planned for a later release.

v2.0.3

v2.0.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 Jul 05:40

v2.0.3 - Fail-Fast Database Bootstrap

Development prerelease. This release is published from dev, may receive
rapid follow-up changes, and is not selected by the default latest image.

Summary

v2.0.3 serializes every startup-time MySQL schema and configuration mutation
under one connection-scoped advisory lock. Migration ledger corruption,
missing recorded schema objects, legacy cleanup failures, baseline migration
failures, versioned migration failures, and default-configuration failures now
stop the server before it accepts traffic.

No new checksummed schema version, image-processing recipe, or upload API is
introduced. This release changes how existing bootstrap work is coordinated,
validated, and reported.

Mandatory First-Upgrade Procedure

Stop every backend instance running v2.0.2 or earlier before starting the first
v2.0.3 instance. Do not use a rolling deployment that overlaps old and new
binaries. Older binaries perform legacy cleanup, baseline AutoMigrate, and
configuration seeding outside the advisory lock now owned by v2.0.3.

After one v2.0.3 instance completes database bootstrap successfully, other
v2.0.3 instances may start normally. They serialize through the same
database-scoped lock.

Changes

Serialized startup bootstrap

  • Replaced four independent startup calls with one
    BootstrapDatabase(ctx, db) entry point.
  • Reserves one physical SQL connection, acquires the MySQL advisory lock on
    that connection, and keeps both through ledger validation, legacy token
    cleanup, baseline migration, versioned migrations, and default seeding.
  • Uses clean GORM sessions for baseline migration and seeding while retaining
    the pinned physical connection.
  • Propagates caller context while waiting for the lock and executing database
    work, and uses a bounded cleanup context when releasing the lock.
  • Returns every stage error to main; the HTTP server no longer starts after a
    partially failed bootstrap.

Migration integrity and recovery

  • Validates known versions, version continuity, migration names, and immutable
    SHA-256 checksums before destructive legacy work.
  • Verifies that columns, indexes, tables, and the capacity-lock seed represented
    by applied ledger entries still exist.
  • Keeps pending operations retry-safe when MySQL has committed some DDL but the
    corresponding ledger entry was not written.
  • Documents that MySQL DDL commits implicitly. Bootstrap recovery is based on
    serialization, object probes, idempotent operations, and retry rather than a
    transaction rollback promise.

Legacy token and configuration compatibility

  • Inspects all four legacy access-token columns in one pass and removes every
    residual legacy column with one ALTER TABLE statement.
  • Deletes incompatible legacy token rows only when token_hash is still
    present. A partially migrated table without that hash keeps modern token
    rows while its remaining old columns are removed.
  • Seeds required configuration with conflict-safe inserts that never overwrite
    administrator values and now reports query or insert failures.
  • Copies the former admin key image_token_default_ttl to the canonical
    private_token_ttl_default_ms key when needed, without overwriting an
    existing canonical value.
  • Corrected the admin web UI to read and write the canonical private-token TTL
    key used by the backend.

Continuous integration

  • Added a pinned MySQL 8.4.10 service to the backend CI job.
  • Added a required real-MySQL bootstrap suite. CI fails instead of silently
    skipping the suite when its DSN is missing.
  • Covers a one-connection pool, repeated bootstrap, full and partial legacy
    token states, invalid and inconsistent ledgers, context cancellation,
    concurrent starters, retry after partially committed DDL, configuration-key
    compatibility, seed failure propagation, and advisory-lock release.
  • Normalized direct Go dependency declarations without changing dependency
    versions.

Verification

  • MySQL 8.4.10 bootstrap integration: 9 scenarios passed.
  • Backend go test ./... -count=1: passed.
  • Backend go vet ./...: passed.
  • Backend go build ./...: passed.
  • Frontend ESLint: passed.
  • Frontend Vitest: 17 test files, 131 tests passed.
  • TypeScript project and Vite production build: passed.
  • Python requirements lock and release-image policy tests: passed.
  • GitBook documentation and translation source-hash verification: passed.
  • The existing wasm-vips direct-eval dependency warning remains unchanged and
    does not fail the build.

Installation

Development images must be pulled explicitly:

docker pull jaykserks/summerain:dev-v2.0.3

Equivalent exact development tag:

jaykserks/summerain:dev-2.0.3

The moving dev tag also points to the newest successful development build.
latest, main, and stable semantic-version aliases are not changed by this
release.

Known Limitations

  • Applied-object validation proves that recorded objects exist; it does not
    compare every column type, default, index column order, constraint, or table
    option with the migration definition.
  • MySQL DDL cannot be transactionally rolled back by this bootstrap. Correct a
    reported failure and restart so idempotent probes can converge the schema.
  • The advisory-lock wait is bounded at 60 seconds. Large historical DDL may
    require an upgrade maintenance window that accommodates startup time.
  • The legacy image_token_default_ttl row is retained for compatibility after
    its value is copied. Runtime reads and new admin writes use only the canonical
    key.
  • Animated image support remains planned for a later release.

v2.0.2

v2.0.2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 Jul 04:31

v2.0.2 - Durable Browser Upload Recovery

Development prerelease. This release is published from dev, may receive
rapid follow-up changes, and is not selected by the default latest image.

Summary

v2.0.2 makes browser upload work recoverable across refreshes, page navigation,
tab closure, and transient network failures. Sources and V2 processing results
are stored in a per-user IndexedDB queue before network side effects begin, and
the client reconciles durable work with server upload-session state when the
upload page is opened again.

There are no database migrations and no server upload-protocol changes in this
release.

Changes

Durable browser queue

  • Added an IndexedDB queue keyed by user and queue ID, with the source file,
    SHA-256 source fingerprint, processing recipe, attempt number, visibility,
    upload-session identity, and retry state stored together.
  • Requests persistent browser storage on a best-effort basis and checks the
    available quota while reserving at least 32 MiB or 10 percent of the quota.
  • Falls back to a clearly labelled current-tab-only item when durable storage is
    unavailable instead of blocking every upload.
  • Applies a 24-hour retention boundary and lazy expiry cleanup. Completed or
    explicitly removed items are deleted immediately when storage is available.
  • Removes persisted processed derivatives after the server enters processing;
    the source remains bounded by completion, explicit removal, or expiry.

Crash-safe V2 upload flow

  • Upload-session ID and expiry are durably recorded before the first part PUT.
  • Persisted processed WebP parts can be reused after interruption without
    decoding and encoding the source again when the recipe still matches.
  • Refresh, navigation, tab closure, and authentication boundaries abort local
    work without implicitly cancelling a recoverable server session.
  • Only explicit removal requests server-side cancellation.
  • Existing idempotency keys remain derived from the queue ID and authoritative
    attempt, preventing an interrupted attempt from publishing twice.

Server reconciliation

  • Reconciles active queue entries through the batch upload-status endpoint and
    recursively isolates missing IDs when the server reports a mixed 4043 batch.
  • Completes already-published entries locally, resumes non-expired part uploads,
    polls sessions already processing, and starts a new idempotent attempt only
    when the previous session is missing or expired.
  • Pauses the queue without destructive state changes when status reconciliation
    is temporarily unavailable.
  • Treats an interrupted legacy V1 request as an unknown, non-retryable outcome
    and asks the user to check My Images before removing or uploading it again.

Multi-tab and account isolation

  • Added renewable per-run leases and transaction-level ownership checks so only
    one tab can mutate a durable queue item at a time.
  • Manual retries are prepared atomically from the authoritative stored attempt
    and upload ID, fencing stale UI state after a lease handoff.
  • Authentication generation guards stop stale login or profile requests from
    restoring a previous account, and login, logout, password change, and remote
    authentication events clear queue data outside the active user boundary.
  • Added localized saving, paused, recovery-ready, current-tab-only, storage, and
    legacy-outcome messages in English, Simplified Chinese, and Japanese.

Dependencies

  • Added exact runtime dependency idb 8.0.3.
  • Added exact test dependency fake-indexeddb 6.2.5.

Compatibility and Resource Behavior

  • The queue uses IndexedDB, Web Crypto SHA-256, Blob, and File APIs supported by
    the V2 browser matrix, including Chromium 93+ and the deployed iOS WebKit 605
    family.
  • Browser image processing remains serial. Queue orchestration admits two items
    concurrently and allows at most four active upload sessions in one tab,
    leaving capacity for recovery or another tab under the server's per-user
    session limit.
  • Server-side image processing, storage layout, recipe 2.0.0, and fixed WebP
    variants are unchanged.

Verification

  • Frontend Vitest: 17 test files, 131 tests passed.
  • ESLint: passed.
  • TypeScript project and Vite production build: passed.
  • Python requirements lock verification: passed.
  • GitBook documentation and translation source-hash verification: passed.
  • The existing wasm-vips dependency direct-eval warning remains unchanged and
    does not fail the build.

Installation

Development images must be pulled explicitly:

docker pull jaykserks/summerain:dev-v2.0.2

Equivalent exact development tag:

jaykserks/summerain:dev-2.0.2

The moving dev tag also points to the newest successful development build.
latest, main, and stable semantic-version aliases are not changed by this
release.

Known Limitations

  • Browsers may evict durable queue data when persistent-storage permission is
    not granted; affected entries are labelled as current-tab-only when the
    initial durable write fails.
  • The 24-hour cleanup is lazy and runs when queue storage is accessed, so expired
    browser data can remain until the upload page is opened again.
  • Legacy V1 uploads do not expose a queryable session identity. An interrupted
    V1 request therefore requires manual confirmation in My Images.
  • Animated image support remains planned for a later release.
  • Real-device acceptance for the supported Chrome and iOS browser matrix is a
    deployment validation step and is not represented by jsdom unit tests.

v2.0.1

v2.0.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Jul 10:33

v2.0.1 - Browser Processing Preflight

Development prerelease. This release is published from dev, may receive
rapid follow-up changes, and is not selected by the default latest image.

Summary

v2.0.1 makes the V2 browser image pipeline fail closed before expensive image
decoding or upload-session creation. Processor selection now uses an actual
wasm-vips and WebP encoder probe instead of relying only on browser features,
and every upload is checked against the complete server recipe before image
processing begins.

There are no database migrations and no server upload-protocol changes in this
release.

Changes

Browser capability negotiation

  • Added a shared, time-bounded wasm-vips worker probe that initializes the WASM
    runtime, its HEIF/AVIF dynamic library, and the WebP encoder.
  • Reuses the successfully probed worker for the first image instead of paying a
    second initialization cost.
  • Uses native pica/Canvas only when the decoded dimensions are within the
    device-specific safe Canvas budget.
  • Rejects large images before upload when wasm-vips is unavailable. The client
    never sends the original image to the backend as an implicit fallback.
  • Keeps low-memory devices out of the WASM path while allowing browsers without
    navigator.deviceMemory to prove support through the real worker probe.

Image preflight

  • Added a single preflight plan that validates the real container format,
    extension and MIME agreement, animation, dimensions, the 50 MP source cap,
    the negotiated server pixel limit, and the WebP 16,383-pixel side limit.
  • Reuses the inspected metadata during processing so the source container is
    not parsed twice.
  • Continues to support static JPEG, JPG, PNG, BMP, WebP, and AVIF inputs.
  • Animated PNG, WebP, AVIF, and other animated inputs remain unsupported in V2.

Recipe contract

  • Added strict Zod validation for numeric limits and the four required variants:
    master, gallery, admin, and publish_source.
  • Rejects changed dimensions, quality, fit mode, pipeline version, or recipe
    version with a stable client error before processing.
  • Uses no-store API requests and invalidates failed recipe lookups instead of
    retaining a rejected cache entry.

Upload feedback

  • Added stable ClientImageError codes for invalid files, unsupported formats,
    animation, dimension limits, processor availability, decode/encode failures,
    timeouts, and unsupported recipes.
  • Added a visible checking stage and localized English, Simplified Chinese,
    and Japanese row-level errors.
  • Invalid files are now retained as explicit rejected queue rows instead of
    disappearing silently.
  • Non-retryable capability and input errors no longer display a misleading
    retry action or produce a large toast burst during bulk selection.

Compatibility and Resource Behavior

  • Images up to the negotiated 50 MP maximum use wasm-vips only after the worker
    and WebP encoder pass a real probe.
  • Canvas fallback remains limited to the calculated 8-16 MP safety budget,
    depending on reported device memory.
  • Image processing remains serial, and each worker is terminated after the
    request so decoded pixels and WASM memory cannot accumulate across the queue.
  • The server still receives only the fixed WebP derivatives defined by recipe
    2.0.0.

Verification

  • Frontend Vitest: 15 test files, 110 tests passed.
  • ESLint: passed.
  • TypeScript project build: passed.
  • Vite production build: passed.
  • The existing wasm-vips dependency direct-eval warning remains unchanged and
    does not fail the build.

Installation

Development images must be pulled explicitly:

docker pull jaykserks/summerain:dev-v2.0.1

Equivalent exact development tag:

jaykserks/summerain:dev-2.0.1

The moving dev tag also points to the newest successful development build.
latest, main, and stable semantic-version aliases are not changed by this
release.

Known Limitations

  • The browser upload queue is not yet persisted. Refreshing, closing, or
    navigating away from the upload page interrupts the current queue.
  • Devices that cannot initialize wasm-vips cannot upload images above their
    safe Canvas budget.
  • Animated image support remains planned for a later release.
  • Real-device acceptance for the supported Chrome and iOS browser matrix is a
    deployment validation step and is not represented by jsdom unit tests.

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 18 Jul 16:59

summeRain v2.0.0

Important

v2.0.0 is an early major release. The upload protocol, browser image
pipeline, schema, compatibility behavior, and operational defaults may still
change frequently. Expect frequent patch releases, review every changelog
before upgrading, and pin an exact version or OCI index digest in production.
Back up MySQL and the complete image volume before the first V2 startup.

This release replaces the V1 upload hot path with a resource-aware V2 pipeline
designed for burst uploads of large images on a 3-core, 4 GB host shared with
other services. It keeps existing V1 images readable while moving new Web
uploads toward deterministic client preprocessing, fixed persisted variants,
durable background publishing, and bounded cleanup.

The V1 comparison baseline for this changelog is tag v0.1.0.

Highlights

  • Moves expensive decode, resize, format conversion, and compression work from
    the server to the browser for new V2 Web uploads.
  • Persists deterministic WebP variants instead of generating thumbnails on the
    first read, eliminating the V1 double-read/double-write hot path for new
    images.
  • Adds resumable, idempotent upload sessions and durable MySQL-backed publish
    jobs, cleanup state, storage lineage, and transactional outbox delivery.
  • Preserves V1 image serving and provides an explicit server-advertised V1
    upload fallback for deployments that disable V2.
  • Adds a bounded deployment profile, disk-pressure admission, finite database
    and Redis pools, and incremental cleanup for constrained shared hosts.
  • Publishes reproducible multi-platform images to Docker Hub and GHCR with a
    recoverable, immutable release-tag workflow.

Full Changelog from V1

Browser-side image processing

  • Added V2 preprocessing for static JPEG, PNG, BMP, WebP, and AVIF inputs.
  • Added signature-based format inspection before decoding, including extension,
    MIME, dimensions, empty-file, and animation validation.
  • Added explicit rejection for animated PNG, WebP, and AVIF files. GIF is not a
    V2 upload format.
  • Enforced a 15 MiB source-file limit and a 50 megapixel source-image limit.
  • Added EXIF-aware orientation handling before crop and resize operations.
  • Added a dedicated wasm-vips worker fast path with HEIF/AVIF decoding,
    single-threaded execution, disabled operation caching, and a bounded tracked
    cache.
  • Added a native fallback based on Pica, ImageBitmap, OffscreenCanvas, and
    Canvas 2D.
  • Added runtime validation that every generated part is a complete WebP
    container before it can be uploaded.
  • Added an eight-minute client-processing timeout, cancellation, and explicit
    worker, bitmap, canvas, blob URL, and object URL cleanup.

V2 generates the following deterministic assets:

Asset Geometry Quality Lifecycle and use
master Original oriented dimensions 80 Persisted full-resolution WebP; owner/admin access
gallery 400x400 cover crop 60 Persisted My Images and dashboard preview
admin 120x160 cover crop 60 Persisted Image Management preview, displayed at 60x80 for 2x density
publish_source Aspect-preserving, longest edge at most 2048 80 Temporary upload part used to create publish
publish Derived from publish_source Server output Persisted public/private publishing asset with optional watermark
  • Added SHA-256, byte size, dimensions, quality, processor version, and recipe
    version metadata to upload manifests.
  • V2 does not preserve the original encoded source bytes. master is the
    full-resolution, quality-80 WebP replacement.
  • All persisted V2 variants are WebP. AVIF is supported as an input format only.

Resumable upload protocol and browser recovery

  • Added the session-based /api/v1/uploads API for recipe discovery,
    initialization, part upload, completion, single and batch status, and
    cancellation.
  • Added required Idempotency-Key handling. The same key and manifest return
    the existing session; a different manifest is rejected.
  • Added durable session states for initialization, transfer, processing,
    completion, failure, cancellation, and cleanup pending.
  • Added all-or-nothing batch status for up to 100 IDs without leaking whether a
    missing ID belongs to another user.
  • Added four-part resumable manifests with strict client/server manifest
    matching.
  • Added byte-accurate XHR progress, two-minute part timeouts, exponential
    backoff with jitter, and up to five part attempts.
  • Added CSRF refresh and replay only for requests explicitly marked idempotent.
  • Added best-effort server-session cancellation after browser cancellation or a
    terminal part failure.
  • Added completion recovery that checks durable server state before retrying an
    ambiguous completion response.
  • Added retry classification that can continue polling, reuse the current
    attempt, or create a new attempt after terminal or expired state.
  • Added adaptive publish polling: 2 seconds for the first 30 seconds, 5 seconds
    until 2 minutes, and 10 seconds afterward, with a 10-minute deadline.
  • Browser processing is limited to one image at a time, upload pipelines to
    two, and active upload sessions to four.
  • Part transfer starts at concurrency two and may increase to three on capable,
    fast, non-metered connections.
  • Upload visibility is fixed for the lifetime of an attempt and cannot be
    changed while the batch is active.
  • The client reads /api/v1/uploads/recipe before preprocessing. It uses the V1
    multipart path only when the server explicitly advertises
    v2_enabled=false.
  • There is no per-file raw-source fallback while V2 is enabled. Browsers that
    cannot use either the WASM or bounded native path receive a clear error.

Backend upload validation and immutable storage

  • Streams each part directly to staging while computing SHA-256 and validating
    byte length, RIFF/WebP structure, dimensions, and animation in one pass.
  • Rejects truncated containers, forged RIFF sizes, trailing bytes, unexpected
    geometry, hash mismatch, invalid MIME/recipe fields, and animated WebP parts.
  • Avoids loading complete V2 parts into Go memory and avoids a second staging
    read solely for format validation.
  • Promotes master, gallery, and admin into immutable content-addressed
    storage and verifies the identity of an already existing target before reuse.
  • Keeps expensive target prevalidation outside the process-level capacity gate
    while retaining serialized transaction and promotion control.
  • Makes completion idempotent and commits the image, fixed variants, quota
    accounting, publish job, and processing event as one durable transition.
  • Deletes publish_source and the upload staging directory after successful
    publish. Upload intermediates are not retained as user-visible assets.

Durable publishing and watermarks

  • Added asynchronous MySQL-backed publish jobs with priority, retry limits,
    leases, renewal, fencing tokens, and expired-worker recovery.
  • Prevents a worker that lost its lease from committing or recreating a stale
    result.
  • Adds compensating cleanup for exhausted terminal jobs instead of leaving an
    image indefinitely half-published.
  • Snapshots watermark configuration when completion creates the publish job, so
    later configuration changes do not alter an already queued image.
  • Applies the server-side watermark only to the final publish asset. Client
    generated master, gallery, and admin remain unwatermarked.
  • Uses atomic watermark replacement, process-local locking, filesystem flock,
    and a recovery journal.
  • Allows jobs with the same watermark snapshot to run concurrently; historical
    snapshots are serialized while the active SVG is safely swapped and restored.
  • Defaults V2 publishing and imgproxy to two workers each, with a documented
    one-worker fallback for more constrained or contended hosts.

Fixed serving routes and V1 compatibility

  • Added fixed V2 routes:
    • /i/<asset_link>.webp
    • /i/<asset_link>/master.webp
    • /i/<asset_link>/gallery.webp
    • /i/<asset_link>/admin.webp
    • /i/<asset_link>/publish.webp
  • Query parameters do not generate additional V2 sizes or formats.
  • master and admin require owner or administrator authorization. Private
    gallery and publish assets retain normal private-image authorization.
  • Existing V1 images remain readable through their original short links.
  • V1 dynamic format, width, height, and quality parameters remain available,
    with dimensions capped at 4096.
  • Existing no-size WebP files and background AVIF outputs may remain persisted.
    Arbitrary V1 transformations now use bounded temporary files and are deleted
    after the final waiting response finishes.
  • Concurrent requests for the same V1 transformation share one imgproxy job.
  • V1 dynamic generation is limited to two active transformations and four
    queued transformation keys; excess work returns a retryable busy response.
  • Background V1 AVIF generation is limited to one operation, enforces a response
    cap, and uses temporary-file plus atomic-rename persistence.
  • With V2 enabled, legacy POST /api/v1/images/ returns 4262. Setting
    V2_UPLOAD_ENABLED=false re-enables the V1 multipart upload endpoint.

Image UI and administration

  • Added separate queue states for local processing, transfer, and server-side
    publication.
  • Replaced raw-source previews with previews from the processed gallery blob.
  • Added per-file retry, batch retry, cancellation on page exit, and deterministic
    object URL cleanup.
  • Changed the upload completion action to copy fixed Markdown containing V2 WebP
    publish links.
  • Removed the upload-page combinations for arbitrary URL/Markdown/BBCode/HTML
    and original/WebP/AVIF output.
  • My Images and dashboard previews now use gallery for V2 images.
  • Image Management uses admin at 60x80 CSS pixels and master for zooming.
  • V2 details e...
Read more

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 15 Jul 09:15