Skip to content

Lanpaper 0.16.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 18:38
· 56 commits to main since this release
84fe55e

Fixed

  • Signing out cannot be undone by the browser's Basic-auth cache. The
    /admin page now accepts only sign-in sessions; HTTP Basic Auth remains
    available to API scripts. Previously, a desktop browser that had cached
    Basic credentials could reopen the panel immediately after session logout.
  • Logout is now durable or explicitly fails. If sessions.json cannot be
    updated, the server keeps the current session, returns an error and lets the
    user retry. It no longer reports success for a revocation that could be
    undone by a restart.

Added

  • Sign out on all devices. Settings → Account can atomically revoke every
    browser session. If persistence fails, all sessions remain valid and the
    operation can be retried; partial revocation is never reported as success.
  • Session lifecycle information. Settings shows the number of active
    browser sessions and the current session expiry. Persisted sessions now have
    opaque IDs and creation timestamps; existing files migrate automatically
    without collecting IP addresses or user agents.

Changed

  • Tested disaster recovery. A new runbook covers complete backup scope,
    checksummed staged restores, drills, audit/repair, corruption and disk-full
    response, credential rotation and safe version rollback. CI now restores a
    destroyed data directory and verifies its durable record in a fresh image.
  • Verifiable release images. CI now emits SPDX and CycloneDX SBOM artifacts;
    release images carry BuildKit SBOM/provenance attestations and a keyless
    Sigstore signature over the immutable multi-platform digest. Digest-pinned
    verification and deployment steps are documented.
  • Hardened production container profile. The maintained Compose example now
    defaults to loopback-only exposure, a read-only root filesystem, bounded
    temporary storage, zero Linux capabilities, no privilege escalation and
    CPU/memory/PID limits. It requires an Argon2id credential instead of a
    plaintext password; CI runs the official image under the same isolation.
  • Bounded processing jobs. Upload and preview work now shares explicit CPU
    and decoded-memory budgets with cancellation-aware queues and pollable
    regeneration progress, while durable publication remains synchronous.
  • Bounded library queries. The list API now supports validated pagination,
    search, access/media filters and stable sorting; legacy arrays are capped
    with explicit truncation headers and the panel loads bounded pages.
  • Resumable SQLite migration. An explicit backup-first command now
    validates and imports JSON metadata in checksummed, checkpointed transactions,
    with dry-run, integrity verification and non-destructive rollback.
  • SQLite metadata backend. A normalized pure-Go backend now implements the
    store contract with WAL, strict foreign-key constraints, atomic transactions,
    integrity checks and online backup while media remains on the filesystem.
  • Wallpaper store boundary. Application services now receive a
    context-aware CRUD/list/transaction interface, with the durable JSON backend
    covered by reusable conformance and atomic-transaction tests.
  • Measured JSON-store limits. Reproducible 1k/10k/50k benchmarks now
    publish allocations, serialization and durable-write latency, with a 10k
    supported ceiling and explicit SQLite migration triggers.
  • Offline and retry UX. The panel now announces connection loss, offers
    reconnect/retry actions, suppresses duplicate uploads and keeps operation
    progress visible without caching administrator or API responses.
  • Validated bulk link import. Link-list imports now dry-run before
    mutation, persist in bounded atomic batches, expose progress/cancellation and
    produce per-record reports without exporting or restoring token secrets.
  • Accessible overlays. Dialog stacking, inert backgrounds, focus
    trap/restore, scroll locking, Escape dismissal, announcements and virtual
    keyboard viewport changes now share one tested controller.
  • Frontend feature modules. Feature code now communicates through an
    immutable capability registry; link-list import/export, upload orchestration,
    and access/history/playlist/settings models are isolated from mutable panel
    state and DOM composition.
  • Frontend state selectors. Link normalization, query/filter/access
    selection, sorting and incremental-render transitions now live in a tested,
    framework-free module separate from DOM composition.
  • Frontend API module. Requests, cancellation, typed errors, retryability
    and session expiry now have one native ES-module implementation with optional
    machine-readable server error codes.
  • Injected remote fetcher. Resolver, transport, clock and temporary storage
    are testable dependencies; network and media-processing concurrency have
    independent bounds while SSRF pinning remains per redirect hop.
  • History and playlist service. History accounting, rollback/deletion and
    playlist metadata/file cleanup now have one injected invariant owner.
  • Injected upload service. Upload source processing, atomic publication and
    metadata commit now flow through an App-owned service with typed stage errors.
  • Explicit authentication runtime stores. Session and token-bucket owners
    can be constructed independently and are isolation-tested. The production
    App references the actual process runtime until request-level injection is
    completed; it no longer advertises unused per-App stores.
  • Application composition root. Production routes now originate from an
    App dependency graph containing immutable configuration, stores, session
    and limiter runtimes, services and structured logging.
  • Token-bucket rate limiting. Public downloads, uploads/regeneration,
    login failures and publish-key failures now use independent continuously
    refilled budgets with bounded bursts and warnings for disabled limits.
  • Security parser fuzzing. Regression-seeded, size-bounded fuzz targets now
    cover multipart input, routes, forwarded/origin headers and persisted media
    metadata normalization.
  • Accessibility and WebKit CI. Browser checks now include axe,
    keyboard/focus restoration, narrow 200% zoom, long translations and Desktop
    Safari-compatible WebKit behavior.
  • Broader browser workflows. Desktop and phone E2E now exercise the media
    lifecycle, access/token changes, history, playlists, link-list migration,
    deletion and multi-tab session expiration.
  • Optional operational metrics. METRICS_ENABLED=true exposes an
    administrator-authenticated /metrics endpoint with bounded-cardinality
    request, upload, session, persistence, rate-limit and disk signals.
  • Structured redacted logging. Runtime logs now use console-readable
    log/slog records with stable event names and centralized secret-attribute
    redaction; legacy messages are bridged during migration.
  • Offline storage repair. lanpaper repair --dry-run plans safe changes;
    --apply quarantines unreferenced files, journals operations, backs up
    metadata and repairs recoverable references under an exclusive lock.
  • Read-only storage audit. lanpaper audit reports missing, orphaned,
    temporary, invalid and metadata-drifted media in text or JSON without
    modifying storage.
  • Explicit upload transactions. Upload publication now enforces ordered
    validate, stage, publish, metadata commit and finalize/rollback boundaries,
    with reverse-order rollback under injected failures.
  • Durable persistence fault injection. Session and wallpaper metadata now
    share a tested atomic-write path covering write, sync, close, rename and
    directory-sync failures without permission-dependent tests.
  • Argon2id administrator credentials. ADMIN_PASSWORD_HASH now takes
    precedence over the deprecated plaintext ADMIN_PASS/JSON adminPass.
    lanpaper hash-password reads a password from standard input and emits a PHC
    value. Credential rotation invalidates fingerprinted browser sessions;
    legacy session files receive a one-time compatibility migration.
  • Unsafe outbound TLS opt-outs are separated. Self-signed remote media can
    be enabled without also disabling HTTPS-proxy certificate verification, and
    vice versa. The broad INSECURE_SKIP_VERIFY switch remains as a deprecated
    compatibility alias for one release.
  • Protected media no longer triggers a browser Basic-auth prompt. auth
    links accept the normal admin session cookie or a Basic Authorization
    header sent preemptively by a script, but never issue WWW-Authenticate.
    This prevents origin-wide cached browser credentials from continuing to
    authorize API calls after session logout.