Commit Graph
1728 Commits
Author SHA1 Message Date
Paul Nothaft 081f3edcdf fix(security): close cross-event thumbnail leak, bulk-op ownership bypass, + hardening
Auth/access-control audit fixes (all pre-existing on main; none are
regressions). Verified end-to-end where noted.

HIGH
- Thumbnail enumeration: photoAuth granted any gallery token access to any
  flat /thumbnails/thumb_* file, so a visitor to one gallery could
  enumerate another (password-protected) gallery's entire thumbnail set.
  Scope thumbnail access to the token's event via photos.thumbnail_path.
  Live-verified: cross-event fetch now 404s, own-event still 200s.
- Bulk ownership bypass: bulk-archive/bulk-delete acted on body-supplied
  event ids with no owner filter (single-event routes enforce
  requireEventOwnership), letting admin/editor archive or cascade-delete
  any event. Add filterOwnedEventIds; also guard rename + import-external;
  tighten photo-retry to scope admin (not just editor). Fix misleading
  bulk-delete comment.

MED
- verifyGalleryAccess never checked decoded.type — assert 'gallery'
  instead of relying on other token types incidentally lacking eventId.
- secure-images generate-token/secure-download missing denySlideshowToken
  (#646 bypass): a leaked slideshow token could download originals.
- Frontend: AuthenticatedImage + api.ts attached the gallery bearer token
  to absolute/external URLs — only attach to relative same-app paths.

LOW hardening
- Pin algorithms:['HS256'] on all auth-boundary jwt.verify calls.
- crypto.timingSafeEqual for share-token + HMAC compares (utils/timingSafe).
- Remove dead photoAuth import in galleryFeedback.

Tests: new regression suites for thumbnail scoping + filterOwnedEventIds;
fixed verifyGalleryAccess.customerRevoke fixture (real customer tokens
carry type:'gallery'). Full backend suite at the pre-existing baseline
(5 suites/27 tests fail on main too), zero new failures.
2026-07-03 10:27:28 +02:00
Paul Nothaft e513e8345b Merge pull request #731 from Luca-Timo/feat/setup-wizard-and-backup-roundtrip
feat: first-run setup wizard (feature selection + config) and portable .picpeak backup roundtrip
2026-07-03 10:03:22 +02:00
Luca fa7665c5b1 fix(backup): address .picpeak review — table filter, superuser guard, tests
From the-luap's review:

- Import no longer trusts manifest.tables blindly. It now intersects the
  manifest's table list with the real data tables of THIS database
  (listDataTables(), which already excludes knex_migrations/_lock) and
  drops anything else. A crafted/corrupted .picpeak listing knex_migrations
  or a non-existent table can no longer wipe it; skipped tables are logged.
- The Postgres session_replication_role='replica' SET (needs superuser) is
  now wrapped: on a managed-PG non-superuser it fails BEFORE any rows are
  deleted (transaction rolls back) and surfaces a clear, actionable 400
  instead of a cryptic permission error.
- Export: on an archiver error, the temp out dir (a partial plaintext-secret
  archive) is now removed instead of orphaned.

Tests (+4, now 26): engine-mismatch rejection, forward-only newer-refused,
non-picpeak rejection, and files/ restored + filesRestored asserted.
2026-07-03 01:39:13 +02:00
Luca 07b450a954 feat(setup): per-feature config step after feature selection
When the chosen features need config the wizard can collect, 'Finish' on
the usage step now advances to a lean config step instead of jumping to
the dashboard:
- Invoicing (if Invoices): company/legal name, address, VAT-ID or tax
  number, IBAN, currency → saved to business-profile + a default bank
  account. Carries the bank/VAT legal disclaimer.
- Email (if reminders/incoming-mail/whatsapp/invoices): SMTP host/port/
  user/pass/from → saved to email_configs.
Each section persists only if started, and 'Skip for now' is always
available — soft settings keep their seeded defaults. en + de strings.
2026-07-02 22:10:54 +02:00
Luca a95ee473ae feat(setup): add restore-from-backup branch to the first-run wizard
The usage step now offers 'Migrating from another PicPeak?' → a restore
step that uploads a .picpeak (reusing PicpeakRestoreCard) to clone another
instance onto this fresh one, preserving the account just created. en + de
strings added.
2026-07-02 21:57:50 +02:00
Luca 86324e7da7 feat(backup): fold .picpeak restore into the Restore wizard's Upload source
Removes the redundant standalone .picpeak card. The wizard's 'Upload
Backup' source now splits into two kinds: '.picpeak backup' (the working
portable restore — renders the upload + destructive-confirm flow inline)
and 'Manifest + files' (legacy, still 'Manifest Upload functionality
coming soon'). en + de strings added.
2026-07-02 21:38:48 +02:00
Luca d4b143f313 fix(setup): keep the first-run wizard light regardless of dark mode
The setup page background used var(--color-background), which flips to
#0a0a0a under the .dark class while the wizard card stays hardcoded light
— giving a dark page + light card mismatch in dark mode. Pin the first-run
screen to its intended light branded look (fixed #fafafa bg / #171717 text)
so all three steps render consistently.
2026-07-02 21:29:47 +02:00
Paul Nothaft b04ef216f5 chore(main): release 3.79.1-beta.0 (#729)
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
v3.79.1-beta.0
2026-07-02 19:03:05 +00:00
Paul Nothaft 4aa6583bae Merge pull request #728 from Luca-Timo/fix/settings-duplicate-mail-import
fix(settings): remove duplicate Mail import that crashes the dev server
2026-07-02 20:59:40 +02:00
Paul Nothaft c8610276c2 Merge pull request #727 from PicPeak/chore/security-nginx-npm-bumps
chore(security): bump frontend nginx to r4 (close 4 HTTP/2 & module CVEs)
2026-07-02 20:53:45 +02:00
Luca cc79b3d9ec refactor(backup): move .picpeak download to the Dashboard tab
Downloading a portable backup is a "make a backup" action, so it belongs
next to "Run Backup Now" on the Dashboard, not under Restore. Split the
combined card into PicpeakExportCard (Dashboard) and PicpeakRestoreCard
(Restore). The manifest stays bundled inside the .picpeak, so there is no
separate manifest-only download for the portable format.
2026-07-02 20:37:35 +02:00
Luca f57462f798 fix(backup): make .picpeak roundtrip work on Postgres
Two Postgres-only bugs found by a live docker-pg roundtrip (SQLite tests
passed because neither reproduces on SQLite):

- Export: knex `.stream()` pulls in the optional `pg-query-stream` module
  (not bundled) and throws on pg. Switched to a plain per-table `select`
  — works on both engines, no new dependency. Rows are DB metadata
  (blobs live under files/), so holding a table in memory is fine.
- Import: the pg driver returns json/jsonb columns as parsed JS values,
  so re-inserting a scalar like the string "PicPeak" sent it unquoted and
  pg rejected it ("invalid input syntax for type json"). Now introspects
  each table's json/jsonb columns and re-serialises those values before
  insert (pg only; SQLite stores json as TEXT and round-trips as-is).

Verified end-to-end on docker Postgres: export 85 tables, full-override
import, current account preserved, post-backup data removed.
2026-07-02 20:13:18 +02:00
Luca 66d61c87ca feat(backup): .picpeak download + upload-restore UI in Backup Manager
Adds a self-contained "Portable backup (.picpeak)" card to the Restore
tab, completing the GUI-only roundtrip:
- Download: optional "include original photos" toggle + a prominent
  plaintext-secrets warning, streams the file via a blob download.
- Restore: file picker → destructive confirmation modal ("replaces ALL
  data except your current account, cannot be undone") → multipart upload
  to /admin/backup/picpeak/import → success summary. If the backup uses
  external media, shows a banner to reconfigure the mount, with a docs link.
Kept separate from the legacy RestoreWizard (different format/flow). en+de
strings added; dark-mode variants throughout.
2026-07-02 19:45:16 +02:00
Luca 2b66f6d889 feat(backup): upload + restore endpoint for .picpeak
POST /admin/backup/picpeak/import — multipart upload of a .picpeak,
streamed to a temp file (after auth, so unauthenticated requests can't
push a large file to disk), then restored via picpeakImportService with
currentAdminId = the logged-in operator (preserved across the override).
Gated on backup.restore. Returns usesExternalMedia so the UI can prompt to
reconfigure the external-media mount. Temp upload is always unlinked.

Completes the backend half of the GUI-only roundtrip (export download +
import upload). Multipart is already allowed by the CSRF content-type guard.
2026-07-02 19:37:17 +02:00
Luca 2920d82186 feat(backup): .picpeak import/restore (full override, keeps current account)
Receiving half of the roundtrip. picpeakImportService.importFromPicpeak():
- Validates the manifest: rejects non-picpeak files, a newer format, an
  engine mismatch (pg↔pg / sqlite↔sqlite only), and a backup from a NEWER
  schema than this instance (forward-only). knex_migrations absence is
  tolerated (test harnesses).
- Snapshots the current logged-in admin, then wipes + reloads every table
  from the backup NDJSON in one transaction with FK enforcement suspended
  (pg: session_replication_role=replica reset before commit; sqlite:
  defer_foreign_keys). knex_migrations is never touched, so the target's
  schema/migration state is preserved.
- Re-injects the current account so the operator is never locked out; a
  backup admin colliding on email is overwritten with the current creds.
- Restores files/ into storage and detects external-media references so the
  caller can prompt to reconfigure the mount.

Roundtrip integration test proves: backup data restored, current account
survives a full override (different email → added), and the email-collision
case keeps the operator's password.
2026-07-02 19:35:48 +02:00
Luca 422dfe1cc8 feat(setup): add "How will you use PicPeak?" feature-selection step
After the admin account is created (and we're logged in), the wizard now
shows an opt-in feature step instead of jumping straight to the dashboard.
Grouped ticks (Client management / Accounting / Automation) map to the
existing feature flags; galleries/analytics/userManagement stay always-on
and are noted, not listed.

- Selection is saved via the existing authenticated PUT /admin/feature-flags,
  whose server-side applyDependencyRules resolves dependencies (e.g. Invoices
  pulls in Accounting) — the wizard only sends raw ticks.
- Labels/descriptions reuse settings.features.<key>.title/description so
  translations stay in sync (en + de verified for all 14 features).
- Saving is best-effort: on failure the admin still enters the app and can
  set features later in Settings.
- New en/de strings for the usage step.

Option A (lean wizard): this is the feature-selection foundation; per-feature
hard-required config steps + the restore-from-backup branch come next.
2026-07-02 19:31:10 +02:00
Luca 38b3aef63d feat(backup): .picpeak portable export (engine-neutral logical snapshot)
First half of the GUI-only backup roundtrip. Adds a self-describing
".picpeak" archive that can be downloaded from one instance and (later)
re-uploaded to another via the web UI only.

- picpeakExportService.createPicpeak(): dumps every table as NDJSON
  (tables introspected at runtime — no hardcoded list, won't rot), plus
  a manifest (format version, app version, DB engine, latest migration,
  per-table row counts + checksums, includePhotos, contains_secrets),
  plus files/ (business-docs + uploads always; original gallery photos
  only when includePhotos). NDJSON is engine-neutral so the target
  rebuilds schema via migrations then loads rows — enabling pg↔pg /
  sqlite↔sqlite and forward-only auto-migrate.
- GET /admin/backup/picpeak/export?includePhotos= streams the file and
  sets X-Picpeak-Contains-Secrets (the file holds plaintext SMTP pass,
  admin hashes, API keys — the UI must warn).
- Purely additive: no existing backup/restore path is touched.

Integration test proves the archive shape, knex-table exclusion, and
row-count/NDJSON consistency (85 tables on the seed schema).
2026-07-02 19:13:58 +02:00
Luca 5b535f8658 fix(settings): remove duplicate Mail import that broke the dev server
SettingsPage.tsx imported `Mail` from lucide-react twice — in the main
icon block (line 20) and again in a later import (line 58). The
@vitejs/plugin-react babel transform rejects the duplicate with
"Identifier 'Mail' has already been declared", so `npm run dev` crashed
when the module loaded. The production `vite build` (esbuild) silently
dedupes it, which is why CI/Docker builds passed and it went unnoticed.

The two imports overlap only on `Mail`; drop it from line 58, keeping
that line's six unique icons (Briefcase, Receipt, ScrollText, Landmark,
Smartphone, MonitorPlay). Verified: single Mail import remains, prod
build passes, and the vite dev transform of SettingsPage now returns 200
with no "already been declared" error.
2026-07-02 17:37:51 +02:00
Paul Nothaft 64e4925fbb chore(security): bump backend npm 10 -> 11 to patch bundled sigstore/tar
Closes Trivy alerts #375 (sigstore CVE-2026-48815), #321 (@sigstore/core),
#314 (tar) — npm@10 bundles the vulnerable sigstore 3.1.0; npm 11 ships the
patched 4.x. Safe because this npm is CLI-only in the final image: runtime
deps come from the builder stage's node_modules and the entrypoint runs node,
not npm, so the install-behaviour issues that motivated the 10.x pin never run
here. npm 11 requires Node >=22.9 — satisfied by node:22-alpine.
2026-07-02 17:16:09 +02:00
Paul Nothaft 12a9d963f5 chore(security): bump frontend nginx to r4 — close 4 HTTP/2 & module CVEs
Trivy flagged nginx 1.28.3-r1 in the frontend image (alerts #371-374):
- CVE-2026-42055 (HIGH) HTTP/2 heap overflow
- CVE-2026-49975 (HIGH) HTTP/2 DoS
- CVE-2026-9256  (HIGH) rewrite_module code exec / DoS
- CVE-2026-48142 (MED)  charset_module memory disclosure

All fixed in nginx 1.28.3-r4. The Dockerfile already ran 'apk upgrade
--no-cache', but the pushed image predated the fixed package and the layer
was cached on r1. Add an explicit nginx upgrade to force the layer to rebuild
against the current Alpine repos (which now carry r4).
2026-07-02 17:14:29 +02:00
Paul Nothaft 24c287d051 chore(main): release 3.79.0-beta.0 (#726)
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
v3.79.0-beta.0
2026-07-02 15:12:45 +00:00
Paul Nothaft 681619f0a1 Merge pull request #718 from PicPeak/feat/setup-wizard-unattended
feat: setup wizard + argument-driven unattended install
2026-07-02 17:08:21 +02:00
Paul Nothaft d35c413651 feat(setup): step-by-step wizard + argument-driven unattended install
Restructure picpeak-setup.sh around two clear modes:

- Interactive wizard (run_wizard): asks method → install dir → channel →
  domain → HTTPS handling → admin email → SMTP, then shows a review and
  confirms before installing. Each value already passed as a flag is
  respected and its question skipped.
- Unattended (--unattended + flags): validate_unattended fills defaults and
  fails fast on impossible combos (e.g. --enable-ssl without --domain).
  New flags: --admin-password, --install-dir, --channel.

Align the Docker path with the rest of the project:
- Use the committed docker-compose.production.yml (prebuilt GHCR images) via
  COMPOSE_FILE in .env instead of hand-generating a divergent compose file.
- Drop the broken setup_ssl_docker call (was referenced but never defined).
- Update path pulls images instead of building.

Admin bootstrap follows the browser-first model (#714): by default no
password is written; the one-time /setup token is surfaced (from
data/SETUP_TOKEN or the logs) with browser instructions. --admin-password
keeps the legacy seeded-admin + ADMIN_CREDENTIALS.txt flow for headless runs.

Depends on #714 (setup-token backend + secrets-init in production compose)
for the browser-first + zero-secret behavior at runtime.
2026-07-02 16:44:09 +02:00
Paul Nothaft 6850bd3bef chore(main): release 3.78.0-beta.0 (#725)
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
v3.78.0-beta.0
2026-07-02 14:35:07 +00:00
Paul Nothaft 97b9853709 Merge pull request #724 from PicPeak/fix/release-automerge-pat
fix: enable release-PR auto-merge with the PAT so releases actually publish
2026-07-02 16:32:04 +02:00
Paul Nothaft bafc96f468 Merge pull request #714 from Luca-Timo/feat/first-run-setup-wizard
feat: zero-config first run — in-browser admin bootstrap + auto-generated secrets
2026-07-02 16:19:33 +02:00
Paul Nothaft e08a33d9ea fix(ci): enable release-PR auto-merge with the PAT, not GITHUB_TOKEN
Auto-merge enabled via GITHUB_TOKEN attributes the eventual merge commit to
github-actions[bot], so recursion prevention suppresses the resulting push to
main — the follow-up release-please run that cuts the tag/release never fires.
Net: the version PR merges but no release/tag/images are ever produced (#719).

Enable auto-merge with RELEASE_PLEASE_TOKEN instead (a real identity) so the
merge triggers the tag-cutting run. Approval stays on GITHUB_TOKEN because it
must be a different identity than the PR author (the PAT) to count as a review.

Observed on #723: merged 3.77.3-beta.0 but no run followed and no tag was cut.
2026-07-02 15:41:25 +02:00
Paul Nothaft 2b2dc6e35c chore(main): release 3.77.3-beta.0 (#723)
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
v3.77.3-beta.0
2026-07-02 13:29:08 +00:00
Paul Nothaft d00d52a221 Merge pull request #722 from PicPeak/fix/release-please-gh-repo
fix: set GH_REPO in release-please auto-merge step
2026-07-02 15:23:49 +02:00
Paul Nothaft e54100ac46 Merge pull request #721 from PicPeak/release-please--branches--main
Build and Push Docker Images / summary (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
chore(main): release 3.77.2-beta.0
v3.77.2-beta.0
2026-07-02 15:23:08 +02:00
Paul Nothaft 0cab43ed89 fix(ci): set GH_REPO in release-please auto-merge step
The auto-merge step runs in a job with no actions/checkout, so gh could not
infer the repository from a git remote and failed with 'not a git repository'
(#719 follow-up). Set GH_REPO=${{ github.repository }} so gh pr list/review/
merge work without a checkout — same fix as the whatsnew workflow (2a5f0a8).

Confirmed working otherwise: with RELEASE_PLEASE_TOKEN set, release PR #721 is
now PAT-authored and its required checks run automatically (no manual approval).
2026-07-02 15:20:07 +02:00
Luca b0912c7427 feat(setup): validate setup token at step 1 before advancing
Previously "Continue" on the token step only checked the field was
non-empty; a wrong token wasn't caught until the final submit, after the
user had filled in email + password. Add a non-burning verify:

- backend: POST /setup/verify-token constant-time compares the token
  without consuming it (createInitialAdmin still claims it atomically on
  submit), gated on no-admin-exists and rate-limited like /setup/admin.
- frontend: step-1 "Continue" calls verifyToken and only advances on a
  valid token; a wrong token shows the invalidToken error on the field,
  429 -> too-many-attempts, 409 -> redirect to login.

Adds integration tests for accept-without-burn / reject / closed-once-set.
2026-07-02 15:18:22 +02:00
Paul Nothaft 95dac43fdf chore(main): release 3.77.2-beta.0 2026-07-02 15:17:15 +02:00
Paul Nothaft fb64ec0910 Merge pull request #720 from PicPeak/fix/release-please-automation
fix: auto-publish release-please PRs without manual approval
2026-07-02 15:16:54 +02:00
Luca 3e69c5df3f fix(setup): match first-run logo size to the login page default
The header logo used a hardcoded 64px frame; the login page renders a
medium (200x150) frame via resolveLoginLogoClasses. Reuse that helper
with the default size so /setup and /admin/login read identically.
2026-07-02 15:03:56 +02:00
Paul Nothaft a3e7232b8e fix(ci): auto-publish release-please PRs without manual approval (#719)
The release PR (authored by github-actions[bot] via GITHUB_TOKEN) sat open
forever: its workflows were held behind 'awaiting approval' and the required
review could not be satisfied by the bot. Both release-please workflows now:

- Use a dedicated ${{ secrets.RELEASE_PLEASE_TOKEN }} (fine-grained PAT) with a
  GITHUB_TOKEN fallback. A PAT-authored PR runs CI automatically (no 'awaiting
  approval') and can be merged without a human.
- Auto-approve (as github-actions[bot], a different identity than the PR
  author) and enable auto-merge on the open release PR, so it publishes once
  checks pass. Skipped when no PAT is configured — falls back to today's manual
  flow, nothing breaks.

A PAT also un-suppresses the tag-push and release-published triggers on
docker-build (GITHUB_TOKEN suppressed them), so add a concurrency group there
to collapse the duplicate same-version builds into one.

Requires (repo/org settings, one-time):
- Create fine-grained PAT RELEASE_PLEASE_TOKEN (contents:write, pull-requests:write).
- Enable 'Allow auto-merge' on the repo (currently off).
- 'Allow GitHub Actions to approve pull requests' — already enabled.
2026-07-02 15:01:52 +02:00
Luca d9b0eb7232 feat(setup): brand first-run screen and split into two-step wizard
Address post-merge UI feedback on the first-run setup screen — the first
screen any new admin sees:

- Use the bundled PicPeak logo (same asset the login page falls back to)
  on the cream brand plate instead of the generic lucide Sparkles icon.
- Split the flow into two steps: step 1 takes only the one-time setup
  token, with the `docker compose logs backend | grep -i "setup token"`
  recovery command shown prominently (with a copy button) directly under
  the field, plus a docs link for when the logs have rotated away; step 2
  collects email + password. A rejected token bounces back to step 1.

en/de strings added; other locales fall back to en.
2026-07-02 14:56:14 +02:00
Paul Nothaft 934cc92bb8 Merge pull request #717 from PicPeak/release-please--branches--main
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(main): release 3.77.1-beta.0
v3.77.1-beta.0
2026-07-02 14:51:09 +02:00
Luca 286975dc52 fix(setup): address PR #714 review — password UX, script token, race, nits
Blockers:
- SetupPage now mirrors the server password rule (>=8 with upper/lower/digit) so
  a green client isn't bounced by the server; server errors carry a `field`
  (routes/setup.js) that the client maps to a translated key instead of
  rendering raw English. New i18n: setup.invalidToken, setup.passwordRequirements.
- picpeak-setup.sh: the ADMIN_CREDENTIALS.txt block no longer dead-ends on the
  wizard path — when no legacy admin was seeded it prints the one-time setup
  token (from data/SETUP_TOKEN / docker compose logs) and points at /setup.

Concern:
- createInitialAdmin creates the admin + burns the token in ONE transaction,
  atomically claiming the token (null-if-present, expect 1 row) so a
  double-submit can't create two super_admins. Cross-DB (whereNotNull, trx-only
  writes). Added a concurrency test.

Nits:
- SetupPage redirects to /login when /setup/status errors (no form flash on a
  configured instance).
- Dropped the unused DATABASE_URL from docker-compose.yml.
- Documented why secrets are chmod 644 (three different reader users).
2026-07-02 13:21:55 +02:00
github-actions[bot] 6f5a02b817 chore(main): release 3.77.1-beta.0 2026-07-02 11:01:34 +00:00
Paul Nothaft f5b4aa7a5b Merge pull request #716 from PicPeak/docs/require-ui-screenshots
docs: require screenshots for UI changes in PRs
2026-07-02 13:01:04 +02:00
Paul Nothaft 8ca74776f4 docs: require screenshots for UI changes in PRs
Any PR that changes a user-facing surface must include a screenshot of the
result in the description (before/after where it helps). Reviewers ask for
one before reviewing UI-touching PRs; backend/non-visual changes are exempt.
2026-07-02 11:57:32 +02:00
Luca 415bffa04c feat: zero-config first run — in-browser admin bootstrap + auto-generated secrets
Fresh installs need nothing in .env. See PR description for the full feature.
2026-07-01 14:49:18 +02:00
Paul Nothaft b8b33ae6d6 Merge pull request #713 from PicPeak/release-please--branches--main
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(main): release 3.77.0-beta.0
v3.77.0-beta.0
2026-07-01 10:00:29 +02:00
github-actions[bot] e1dae31e16 chore(main): release 3.77.0-beta.0 2026-07-01 07:55:55 +00:00
Paul Nothaft e873f7c98c Merge pull request #712 from PicPeak/chore/conventional-pr-title-guard
feat: admin photos list/grid toggle + upload failure report (#707, #708)
2026-07-01 09:55:37 +02:00
Paul Nothaft 6f95796b7c feat: admin photos list/grid toggle + upload failure report (#707, #708)
Records two features that merged with gitmoji commit subjects and were
therefore skipped by Release Please, so the next beta credits them:
- #707 grid/list layout toggle on the admin Photos tab
- #708 per-file upload failure report in the upload modal

No code change — the features are already on main; this commit only gives
Release Please a Conventional Commit to cut the release from.
2026-07-01 09:38:34 +02:00
Paul Nothaft 4881d2040a ci: validate PR titles against Conventional Commits
Release Please only recognizes Conventional Commit prefixes (feat:, fix:,
...). PRs merged with other conventions (gitmoji, free-form) are silently
skipped, shipping changes with no version bump or changelog entry (see
#707/#708). Fail such PRs early via amannn/action-semantic-pull-request.
2026-07-01 09:38:34 +02:00
Paul Nothaft b8665e1d86 Merge pull request #708 from andredlng/feat/upload-failure-details
Surface which files failed during photo upload
2026-07-01 09:29:19 +02:00
Paul Nothaft f4a1db8b6a Merge pull request #707 from andredlng/feat/photos-list-view
Add grid/list layout toggle to admin Photos tab
2026-07-01 09:00:31 +02:00