Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7a8ec71
feat(loans): allow multiple physical copies per borrower
fabiodalez-dev Aug 20, 2026
40662cb
fix(loans): address multiplicity review findings
fabiodalez-dev Aug 21, 2026
d9436a6
fix(loans): centralize copy commitment policy
fabiodalez-dev Aug 21, 2026
027dd2a
refactor(loans): share open commitment states
fabiodalez-dev Aug 21, 2026
5d16a55
test(e2e): cover the multiple-copy loan desk flow end-to-end (#238)
fabiodalez-dev Aug 21, 2026
0f54a81
chore(release): bump to 0.7.64 and document multiple-copy loans (#238)
fabiodalez-dev Aug 21, 2026
de6462a
test(e2e): restore the multiplicity setting byte-for-byte in cleanup
fabiodalez-dev Aug 21, 2026
555d3ff
fix(loans): harden approval and pickup against out-of-house copies (#…
fabiodalez-dev Aug 21, 2026
d04b3e1
fix(reservations): queue eligibility, copyless books and admin edit g…
fabiodalez-dev Aug 21, 2026
c557e00
fix(loans): desk-flow and return-flow follow-ups to #368
fabiodalez-dev Aug 21, 2026
9ff8ab4
fix(circulation): serve every compatible hold per freed copy
fabiodalez-dev Aug 21, 2026
a8ee132
fix(notifications,cron): pickup-ready retry, email-less borrowers, cr…
fabiodalez-dev Aug 21, 2026
98d9274
fix(ncip): partner enforcement, per-user loan resolution, full transa…
fabiodalez-dev Aug 21, 2026
5c66f93
docs(changelog): document the circulation review fixes and seed the n…
fabiodalez-dev Aug 21, 2026
1e24a26
test(mvcc): accept the eligibility batch size in the queue locking-re…
fabiodalez-dev Aug 21, 2026
3e72e23
fix(static): satisfy PHPStan level 5 on the pickup-claim revert and t…
fabiodalez-dev Aug 21, 2026
b7b17b4
fix(review): address CodeRabbit findings on #370
fabiodalez-dev Aug 21, 2026
90d2852
test: align related-books responsive spec with the snap-strip layout
fabiodalez-dev Aug 21, 2026
77cd15a
test: align ultra-wide related-books bound with the 1320px wrap cap
fabiodalez-dev Aug 21, 2026
6e94a50
fix: harden pickup-notification claim and NCIP partner edge cases
fabiodalez-dev Aug 21, 2026
c399ff3
fix(review): harden circulation and release readiness
fabiodalez-dev Aug 21, 2026
8c674a8
ci: document the attestations permission for zizmor
fabiodalez-dev Aug 21, 2026
4da2c97
ci: define STDOUT/STDERR in stdin-fed PHP upgrade-smoke scripts
fabiodalez-dev Aug 21, 2026
344798a
fix(review): close final circulation findings
fabiodalez-dev Aug 21, 2026
c4dbb0a
test: arrange stale-predecessor fixtures in trigger-valid order
fabiodalez-dev Aug 21, 2026
cb3ca58
ci: drop route scope from the ZAP 13-digit ISBN allowlist
fabiodalez-dev Aug 21, 2026
8c2034c
fix: address CodeRabbit round on notifications, NCIP and release tooling
fabiodalez-dev Aug 21, 2026
430094c
test: align static loan-edge-case contract with the 66-test suite
fabiodalez-dev Aug 21, 2026
8096523
test: gate multiple-copy-loans-238 on E2E_DB_NAME like real-world-25
fabiodalez-dev Aug 21, 2026
61f2df5
ci: harden browser regression gates
fabiodalez-dev Aug 21, 2026
7c0c7c0
ci: distinguish shipped ISBN examples from PII
fabiodalez-dev Aug 21, 2026
fc779ab
ci: constrain public ISBN example allowlist
fabiodalez-dev Aug 21, 2026
4cbe930
fix: enforce overdue copy intervals symmetrically
fabiodalez-dev Aug 21, 2026
dc38689
fix(ncip): audit idempotent check-ins
fabiodalez-dev Aug 21, 2026
3415048
fix: align loan triggers with application date
fabiodalez-dev Aug 21, 2026
b24372e
fix(ncip): serialize request lifecycle mutations
fabiodalez-dev Aug 21, 2026
898014a
fix(release): use supported paginated gh queries
fabiodalez-dev Aug 21, 2026
75f8861
test: fetch the one-time loan submission token in loan-overlap C-group
fabiodalez-dev Aug 21, 2026
a7ba935
ci: drop unused google-chrome apt source before playwright install
fabiodalez-dev Aug 21, 2026
088188f
fix(ci): remove unused Chrome apt source before refresh
fabiodalez-dev Aug 21, 2026
0b16d68
ci: verify flagged ZAP PII digits against fresh fetches
fabiodalez-dev Aug 21, 2026
70d2dd1
ci: silence SC2034 in the ZAP re-fetch loop
fabiodalez-dev Aug 21, 2026
7f10155
test: bind the application date on unit-suite DB connections
fabiodalez-dev Aug 21, 2026
b913fa8
fix(security): prevent CSRF tokens from resembling PII
fabiodalez-dev Aug 21, 2026
6a46b89
fix(ci): keep ZAP PII checks fail closed
fabiodalez-dev Aug 21, 2026
75c1a9c
fix(security): prevent CSP nonces from resembling PII
fabiodalez-dev Aug 21, 2026
1c45b44
fix(security): harden CSP nonce validation
fabiodalez-dev Aug 21, 2026
3b2872f
fix: address CodeRabbit round on NCIP responses and release policy
fabiodalez-dev Aug 21, 2026
f9996e2
fix: close final CodeRabbit review gaps
fabiodalez-dev Aug 21, 2026
8002e39
fix(users): localize the stored sesso enum on admin user details
fabiodalez-dev Aug 22, 2026
f3b14eb
chore(migration): name the pickup-notification migration -rc.1
fabiodalez-dev Aug 22, 2026
8d2fa5a
fix(loans): keep approval flexible for date-disjoint out copies (F2)
fabiodalez-dev Aug 22, 2026
d8599b2
fix(loans): surface a clear error when backdating a due date (F1)
fabiodalez-dev Aug 22, 2026
31cad53
fix(ui): stop the notifications dropdown from clipping on phones
fabiodalez-dev Aug 22, 2026
2eca9c6
test(loans): add 25 checks for the 0.7.64 circulation release
fabiodalez-dev Aug 22, 2026
7c2b766
ci(upgrade-smoke): match the migration record on the -rc.1 version
fabiodalez-dev Aug 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 54 additions & 10 deletions .github/workflows/ci-browser-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ jobs:

- name: Install Apache and packaging tools
run: |
# The hosted runner image ships Google's chrome-stable apt source,
# which these jobs never install from. Remove it before the first
# apt refresh so a mid-sync Google mirror cannot break the job.
sudo rm -f /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update -q
sudo apt-get install -y apache2 libapache2-mod-php jq rsync unzip zip
sudo a2enmod rewrite headers env
Expand Down Expand Up @@ -160,9 +164,49 @@ jobs:
allow_issue_writing: false
artifact_name: zap-baseline-${{ github.run_id }}

- name: Test narrow ZAP bibliographic PII allowlist
run: bash tests/zap-pii-filter.test.sh

- name: Fail on medium or high ZAP alerts
run: |
test -s report_json.json || { echo "ZAP JSON report is missing"; exit 1; }
set -euo pipefail
identifiers_file="$RUNNER_TEMP/zap-catalogue-identifiers.json"
public_urls_file="$RUNNER_TEMP/zap-public-catalogue-urls.json"
public_examples_file="$RUNNER_TEMP/zap-public-example-identifiers.json"

MYSQL_PWD="$E2E_DB_PASS" mysql \
-h "$E2E_DB_HOST" -P "$E2E_DB_PORT" -u "$E2E_DB_USER" \
-N -B "$E2E_DB_NAME" -e '
SELECT identifier
FROM (
SELECT isbn13 AS identifier FROM libri WHERE deleted_at IS NULL
UNION
SELECT ean AS identifier FROM libri WHERE deleted_at IS NULL
) AS catalogue_identifiers
WHERE identifier REGEXP "^[0-9]{13}$"
ORDER BY identifier
' | jq -Rsc 'split("\n") | map(select(length > 0)) | unique' > "$identifiers_file"

# The single-quoted PHP program is intentional; its $variables must
# reach PHP literally rather than expand in the runner shell.
# shellcheck disable=SC2016
curl -fsS http://localhost:8081/sitemap.xml \
| php -r '
$xml = simplexml_load_string(stream_get_contents(STDIN), SimpleXMLElement::class, LIBXML_NONET);
if ($xml === false) { fwrite(STDERR, "Invalid sitemap XML\n"); exit(2); }
$urls = [];
foreach ($xml->url as $entry) { $urls[] = (string) $entry->loc; }
echo json_encode(array_values(array_unique($urls)), JSON_UNESCAPED_SLASHES), PHP_EOL;
' > "$public_urls_file"

# Translation dictionaries are intentionally inlined client-side.
# Extract only canonical, explicitly named ISBN example keys. The
# checked-in jq program requires a full 978/979 match and a valid
# ISBN-13 checksum, so unrelated numbers and longer substrings cannot
# become origin-wide exceptions.
jq -f scripts/ci-zap-public-isbn-examples.jq \
locale/it_IT.json > "$public_examples_file"

# OWASP ZAP rule 10062 (PII Disclosure) is allowlisted NARROWLY, never
# globally. A book catalogue renders ISBN/EAN-13 identifiers on its
# bibliographic pages, and a 13-digit code inherently collides with the
Expand All @@ -171,15 +215,15 @@ jobs:
# 413167 is a Visa range). An alert is ignored ONLY when EVERY instance
# is a 13-digit number on a bibliographic route — a real card leak
# (15/16 digits) or a 13-digit value on any other page still fails the
# build. Real secret/PII exposure is also covered by the secret-scanning,
# Semgrep and CodeQL jobs; every other medium/high alert stays blocking.
FILTER='def is_isbn_fp: (.pluginid // "") == "10062" and ([ .instances[]? | ((.evidence // "") | test("^[0-9]{13}$")) and ((.uri // "") | test("/(auteur|author|autor|autore|book|buch|catalog|catalogo|catalogue|editore|editori|genere|genre|katalog|libro|libri|livre|publisher|verlag)"; "i")) ] | (length > 0 and all)); [ .site[]?.alerts[]? | select((.riskcode | tonumber) >= 2) | select(is_isbn_fp | not) ]'
blocking=$(jq "$FILTER | length" report_json.json)
if [ "$blocking" -gt 0 ]; then
jq -r "$FILTER"' | .[] | "[" + (.riskdesc // "") + "] " + (.alert // "") + ": " + (.desc // "")' report_json.json
exit 1
fi
echo "ZAP found no blocking medium/high passive-scan alerts (allowlisted: 13-digit ISBN/EAN codes on bibliographic pages)"
# build. The checked-in filter also requires GET with empty param/attack,
# an exact registered route (canonical URLs come from the live sitemap)
# when evidence is a live catalogue identifier. The only route-wide
# exception is the exact public example strings shipped in the inlined
# translation dictionaries. Real secret/PII exposure is also covered
# by secret scanning, Semgrep and CodeQL; every other medium/high alert
# stays blocking.
bash scripts/ci-check-zap-report.sh \
report_json.json "$identifiers_file" "$public_urls_file" "$public_examples_file"

- name: Upload browser and server diagnostics
if: always()
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci-deep-regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ jobs:

- name: Install Apache, PHP module, MySQL client and mail transport
run: |
# This job never installs Google Chrome. Remove its hosted-runner
# apt source before the first refresh so mirror syncs cannot break CI.
sudo rm -f /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update -q
sudo apt-get install -y apache2 libapache2-mod-php default-mysql-client msmtp-mta
sudo a2enmod rewrite headers env
Expand Down Expand Up @@ -279,6 +282,9 @@ jobs:
persist-credentials: false
- name: Install Apache and PHP module
run: |
# This job never installs Google Chrome. Remove its hosted-runner
# apt source before the first refresh so mirror syncs cannot break CI.
sudo rm -f /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update -q
sudo apt-get install -y apache2 libapache2-mod-php default-mysql-client
sudo a2enmod rewrite headers env
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ jobs:
# supports PHP >= 8.1, so the Ubuntu mod_php package is sufficient here.
- name: Install Apache2 + mod_php
run: |
# This job never installs Google Chrome. Remove its hosted-runner
# apt source before the first refresh so mirror syncs cannot break CI.
sudo rm -f /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update -q
sudo apt-get install -y apache2 libapache2-mod-php
sudo a2enmod rewrite headers env
Expand Down
Loading