Skip to content

release: v1.6.69 - #294

Open
roncodes wants to merge 12 commits into
mainfrom
release/v1.6.69
Open

roncodes wants to merge 12 commits into
mainfrom
release/v1.6.69

Conversation

@roncodes

@roncodes roncodes commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Release v1.6.69

Release branch for core-api v1.6.69. Merging into main triggers release.yml, which validates that composer.json and the first line of RELEASE.md name 1.6.69, then pushes the v1.6.69 tag.

This branch collects:

Before merging

- Drop the 'public' visibility from Utils::urlToStorefrontFile: a bucket with
  BucketOwnerEnforced rejects any PUT carrying an ACL, so put() returned false.
- Add File::signStoredUrl()/s3KeyFromUrl(): turn absolute URLs stored as strings
  (legacy unsigned bucket URLs, expired signed URLs) back into a key and re-sign.
- Re-sign template builder image src at render time.
- Cache signed URLs for 60 of their 120 minutes so every URL handed out has at
  least an hour left; cut Extension icon_url cache from 24h to 30m.
Replace the db:backup command, which piped mysqldump through gzip without
pipefail, swallowed upload errors and returned success on a failed dump.
That is how production uploaded 20-byte empty dumps on 2026-09-24/25 (no
mysqldump in the image) and then nothing at all while reporting DONE.

- DatabaseBackupService streams the dump client's stdout into gzip in PHP
  (no shell pipeline), passes the password via MYSQL_PWD, and fails a run
  on a non-zero exit, a missing '-- Dump completed' marker, a dump under
  min_size_bytes, or an uploaded object whose size differs from the file.
- Uploads go to any filesystem disk (bucket override for s3, key prefix);
  retention by age and/or count runs only after a fully successful run and
  always keeps each database's newest backup.
- Every attempt is recorded in database_backups (status, size, duration,
  error, trigger); failures can email configured addresses.
- Settings live in system.database-backups (env defaults in
  config/database-backups.php) and drive the schedule; disabled by default.
- Admin endpoints under int/v1/database-backups: settings get/save/reset,
  recent runs, and a queued 'run now'.
- db:backup exits non-zero on any failure; --force runs while disabled.
Add VerificationCode::issue(), check() and attemptsLeft() for flows where a
leaked table must not give away live codes:

- issue() stores an HMAC of the code, keyed by the app key, and hands the
  plain code back once on the instance (plainCode), defaulting to a 10-minute
  expiry and an 'active' status.
- check() compares with hash_equals, counts wrong attempts in meta and locks
  the code on the last allowed one. Expired and locked codes report as such.
- The creating hook keeps a code that was already set, so issue() is not
  overwritten; codes made the old way still get a random one and still check.

Existing generators and their callers are unchanged. First user: the FleetOps
public tracking page's one-time codes.
getCountryCodeByCurrency() and getCountryCodeByName() rebuilt the full
countries dataset (a 4.7 MB JSON file plus flag hydration) on every call.
Storefront serializes a country per store, so listing stores paid that cost
once per record and network store lists could take minutes.

The name/ISO2/currency rows are now built once, kept in the application
cache and memoized per process. Cache failures fall back to building the
lookup, and flushCountryLookup() resets it.
Store media, product images and proofs of delivery are looked up by
subject_uuid, which had no index, so each lookup scanned the whole files
table.
fix(files): support a fully private S3 media bucket
feat(backups): settings-driven database backups that fail loudly
feat(verification): hashed one-time codes with attempt counting
perf: cache the country lookup and index files.subject_uuid
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