Skip to content

Upgrade vanilla base 7.6.5 → 7.6.7 (diff-apply two-parent merge) - #1398

Open
milanmajchrak wants to merge 1498 commits into
dtq-dev-767-basefrom
upgrade/vanilla-7.6.7
Open

Upgrade vanilla base 7.6.5 → 7.6.7 (diff-apply two-parent merge)#1398
milanmajchrak wants to merge 1498 commits into
dtq-dev-767-basefrom
upgrade/vanilla-7.6.7

Conversation

@milanmajchrak

@milanmajchrak milanmajchrak commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Upgrades the fork's vanilla base from 7.6.5 to 7.6.7. Pairs with dataquest-dev/DSpace#1383 — merge and deploy that one first (the authorized-selector work calls new BE discovery endpoints and needs a full reindex).

Problem

The fork sat on vanilla 7.6.5, missing two maintenance releases.

Root cause of the awkward merge

git merge-base dtq-dev vanilla is dspace-7.6.1, not 7.6.5 — the fork carries 7.6.2–7.6.5 textually, not as ancestry. A plain git merge dspace-7.6.7 re-litigates the whole range: 174 conflicted files.

Change set

Applied only the true 7.6.5→7.6.7 delta (git merge-tree --merge-base=dspace-7.6.5) = 29 conflicts, committed via git commit-tree as a real two-parent merge so merge-base is permanently repaired.

Commit What
c08c189833 the merge itself (^1 = fork ac786377, ^2 = dspace-7.6.7), 29 conflicts resolved per recipe + fixups
0bef214107 two blockers fixed: sanitize-html pin, locale specs aligned
c1bc451158 sanitize-html moved from 2.17.4 to 2.17.5 (see below)

Test evidence

CI green on the head being merged (c1bc451158) — both matrix legs, 4 success + 1 skipped (deploy, skipped on PRs by design). The tests job ran the full battery (previously it died in ~1 min at install, so lint/build:prod/karma/e2e had never executed at all):

Step Result
yarn install --frozen-lockfile Done in 51.95s
yarn run lint --quiet Done in 97.87s
yarn run check-circ-deps No circular dependency found
yarn run build:prod browser 233s + server 186s
yarn run test:headless TOTAL: 5488 SUCCESS
docker compose -f docker/docker-compose-ci.yml up -d stack up — exercises the compose network fixup
cypress e2e All specs passed
serve:ssr + ~15 route probes /home, communities, collections, 7× entities, /handle/…, /403, /404, /500

Feature parity vs dtq-dev: 0 files deleted (13A/171M/0D/0R), all 171 CLARIN-named files survived and the merge touched none of them, 0 specs lost (837→840), 0 i18n keys lost across all 28 catalogues, cs/en CLARIN keys 167→167.

The two blockers 0bef214107 fixes

1. yarn.lock: sanitize-html floated to 2.17.6, which requires node >=22.12.0. CI runs [18.x, 20.x], so yarn install --frozen-lockfile failed on both legs and the entire FE CI was red. 2.17.6 also pulls htmlparser2@^12 whose subgraph (6 more packages) requires node >=20.19.0.

Pinned in the lock only; package.json is unchanged (^2.17.4 is the correct vanilla range). The orphaned htmlparser2@12 subtree was pruned.

Two mechanics worth recording: a plain yarn install does not fix this (^2.17.4 still admits 2.17.6), and resolutions does not work either — yarn 1 does not apply resolutions to direct dependencies (verified). The pin has to live in the lock.

The pin landed on 2.17.5, not 2.17.4 (c1bc451158). 2.17.4 was the wrong stopping point: the engines.node >=22.12.0 problem is specific to 2.17.6, while 2.17.5 has no engines field at all and still depends on htmlparser2 ^10.1.0 — the version already hoisted here — so it was available at no cost. And "no GHSA advisory is patched in 2.17.5" turned out to be an unsound safety argument, because 2.17.5 carries undisclosed XSS hardening:

  • allowedSchemesAppliedToAttributes grows from 3 to 20 entries, so a javascript: URL in formaction, action, data, xlink:href, poster and 12 others is now scheme-checked — 2.17.4 let those through
  • the srcset check is extended to imagesrcset
  • tagAllowed() guards are added to the raw-text passthrough branches, the code path of the critical GHSA-rpr9-rxv7-x643

Verified after the change: htmlparser2 stays 10.1.0, no engines error on node 20.19.0, --frozen-lockfile is Already up-to-date, lint clean, test:headless TOTAL: 5488 SUCCESS. The only source using sanitize-html is markdown.pipe.ts; none of the 17 newly scheme-checked attributes appear in its MathJax allowlist and the rendered MathJax SVG is byte-identical between 2.17.4 and 2.17.5. 2.17.6 remains blocked on the node bump.

2. locale.service.spec.ts was byte-identical to vanilla and tested the Observable API while the implementation had been (correctly) reverted to a synchronous getCurrentLanguageCode(): string. That produced 7× TS2345 → karma Found 1 load error → not one of the 5488 tests ran. The whole suite was dead.

This slipped through because tsconfig.app.json excludes src/**/*.spec.ts, so build:prod — the only type gate the previous run executed — never compiles specs. Specs were aligned to the implementation (not the reverse); the vanilla getLanguageCodeList block is untouched. Also dropped subs/ngOnDestroy in locale.service.ts, left dead by the revert and never present in the fork.

Decision D7 — SUPERSEDED, see "D7 was not implemented as decided" below

Answered: "prefer vanilla, if it does not break any CLARIN functionality." The text below described
the opposite and was not what shipped. ff96c2cada takes vanilla's Observable<string> version
verbatim and adds a separate getCurrentLanguageCodeSync() for the 5 fork call sites. Kept for the
record only.

Vanilla 7.6.6 PR DSpace#4905 changed getCurrentLanguageCode() to return Observable<string>. We do not take that part: 5 fork call sites consume it synchronously — header.component.ts:47,55,64, CLARIN-only clarin-license-info.component.ts:103, CLARIN-only html-content.service.ts:100. With the Observable version the Czech UI, CLARIN license info and localized static HTML pages would silently stop working.

getLanguageCodeList(ignoreEPersonSettings) is taken from vanilla (the auto-merged locale.interceptor.ts needs it). That switches on reading eperson.language. Measured live rather than assumed:

  • logged in, UI=en → Accept-Language: en;q=1,cs;q=0.5; UI=cs → cs;q=1,cs;q=0.5
  • logged out → en;q=1, no cs
  • GET /server/api (HAL root) exactly once, no Accept-Language, no Authorization — the ignoreEPersonSettings guard plus take(1) do prevent the circular EPerson request

setQuality() divides by 2 for LANG_ORIGIN.EPERSON, so eperson.language is always below the UI language and never drives the UI. The behavioural change is therefore smaller than the plan assumed.

Risk

  • ui.baseUrl must be set in the deployment overlay. 7.6.7 removed the Host-header trust (getCurrentOrigin). The fork's config/config.yml has no ui: block at all and default-app-config.ts hardcodes http://localhost:4000, so SSR will boot but the legacy-bitstream 301 Location and the Sitemap: line in /robots.txt will point at localhost. Set DSPACE_UI_BASEURL (or DSPACE_UI_HOST/PORT/SSL/NAMESPACE). Fixed in ff96c2cada: docker/docker-compose.yml now sets it, defaulting to UI_URL and hard-failing when neither is present.
  • Future yarn install without --frozen-lockfile can float sanitize-html back to 2.17.6. An exact pin in package.json would prevent that, at the cost of diverging from vanilla.
  • e2e passing here does not cover CLARIN-specific flows (license-gated download, preview/tgz, Shibboleth) — those need fixtures.

Rollback

Reset the branch to ac786377, or revert 0bef214107 and ff96c2cada (the audit fix). Nothing is deployed by merging.

Non-goals / still open

Playwright suite, browser-level probes (authorized-selector dialog, clarin-license-info, html-content.service, language switch while logged in) — the host's cypress binary is broken so these were verified at REST/SSR level instead.

Sign-off status: D1, D5 and D7 were answered by the maintainer and are implemented (D7 only after the
audit caught that it had not been). D2, D3, D4 and D6 were queried, explained in UPGRADE_767_QUESTIONS.md,
and still have no decision — the branch ships the documented default for each. Merging accepts those
defaults.

🤖 Generated with Claude Code


⚠️ Deployment prerequisite found by the final review — read before deploying

DSPACE_UI_BASEURL must be set, or every absolute URL points at localhost:4000.

7.6.7 changed two things at once: it added a hardcoded baseUrl: 'http://localhost:4000' to src/config/default-app-config.ts (7.6.5 had none), and it removed getCurrentOrigin, the Host-header trust (7.6.5 had 10 references, 7.6.7 has 0).

config.server.ts derives baseUrl from DSPACE_UI_HOST/PORT/SSL/NAMESPACE only if (isEmpty(config.baseUrl)). After the upgrade it is never empty, so those four variables — which docker/docker-compose.yml does set — are now silently ignored, and that file sets no DSPACE_UI_BASEURL.

Consequence on any instance whose public URL is not localhost:4000: the legacy /bitstream/handle/... 301 Location and the Sitemap: line in /robots.txt point at localhost. For LINDAT that breaks historic citation URLs, and it fails silently.

DSPACE_UI_BASEURL is applied correctly when set (verified live: Applying environment variable DSPACE_UI_BASEURL with value ...). Left for the deployer to set rather than hardcoded here, since the value differs per instance.


ui.baseUrl prerequisite — now enforced (8884b9f6d1), added 2026-08-03

The prerequisite above is no longer just a note. docker/docker-compose.yml now declares

DSPACE_UI_BASEURL: ${DSPACE_UI_BASEURL:?set it in .env to the public UI URL, e.g. https://lindat.example.org/repository}

with no default, so a deploy that forgets it fails loudly instead of silently serving localhost URLs. Verified:

$ docker compose -f docker-compose.yml config
error while interpolating services.dspace-angular.environment.DSPACE_UI_BASEURL:
required variable DSPACE_UI_BASEURL is missing a value: set it in .env to the public UI URL, ...
$ DSPACE_UI_BASEURL=https://example.org/repository docker compose -f docker-compose.yml config | grep BASEURL
      DSPACE_UI_BASEURL: https://example.org/repository

Action required before merging is deployed: add DSPACE_UI_BASEURL to each instance's env file —
deploy.yml passes --env-file /opt/dspace-envs/.env.dspace.dev-5 (instance 5) and
.env.dspace.imported.dev-5 (instance 8). CI is unaffected: docker-compose-ci.yml has no dspace-angular service.

The finding is now proven, not just read out of the code

The earlier probe was vacuous — the rehearsal URL happened to equal the hardcoded default. Measured through
buildAppConfig() in src/config/config.server.ts:

Environment resolved ui.baseUrl
nothing set http://localhost:4000
DSPACE_UI_SSL=true HOST=lindat.example.org PORT=443 NAMESPACE=/repository (what compose used to do) http://localhost:4000
DSPACE_UI_BASEURL=https://lindat.example.org/repository https://lindat.example.org/repository

The middle row is the evidence that was missing: the host and port are picked up (ui.host becomes
lindat.example.org, ui.port becomes 443) — baseUrl simply is not derived from them any more.

README-dtq.md documents the variable in the .env section.


Audit round (2026-08-04) — two real defects, both fixed in ff96c2cada

D7 was not implemented as decided

The instruction was to prefer vanilla unless it breaks CLARIN functionality. locale.service.ts on
dtq-dev-767-base is byte-identical to dspace-7.6.5 — the fork never customised it, so a 3-way
merge could not have conflicted — yet this branch carried a third blob with 7.6.5's logic. That dropped
vanilla's language-detection fix: the full Accept-Language q-list scan, case-insensitive matching
(DE and en-GB fell through to defaultLanguage), and "do not cookie an auto-detected language".
The specs had been rewritten to assert the old behaviour and vanilla's case-insensitivity test deleted,
so the green suite proved nothing.

All three files are byte-identical to dspace-7.6.7 again. The five CLARIN call sites are synchronous
template getters and vanilla's method must be an Observable (getLanguageCodeList() depends on the auth
state), but they want the language currently in effect, not language negotiation — so they use a new
additive getCurrentLanguageCodeSync(). The CLARIN test lives in its own locale.service.clarin.spec.ts
so the upstream spec stays byte-identical.

The DSPACE_UI_BASEURL guard would have bricked every deploy

UI_URL already feeds the backend's dspace.ui.url — the same value ui.baseUrl is documented to hold —
and every other compose file in the repo (cli.yml:35, docker-compose-rest.yml:37,
docker-compose-ci.yml:27) reads it as ${UI_URL:-http://127.0.0.1:4000}, i.e. with a default.
It was set in build-scripts/run/envs/.default but not in .local; this branch adds it there. Requiring a brand-new variable with no default meant
start.sh, deploy.yml and the documented docker/README.md recipes would all abort, and an override
compose file cannot rescue it because compose interpolates per file before merging.

DSPACE_UI_BASEURL now defaults to UI_URL and fails only when neither is set:

envs/.default (UI_URL only)  -> DSPACE_UI_BASEURL: http://dev-5.pc
neither set                  -> error: required variable UI_URL is missing a value
DSPACE_UI_BASEURL explicit   -> wins over UI_URL

Corrections to earlier claims

  • The blast radius is wider than stated. ui.baseUrl also feeds the Google Scholar
    citation_pdf_url and citation_abstract_html_url meta tags on every item page, and the statistics
    referrer — not just robots.txt and the legacy 301.
  • This is not a regression the upgrade introduced. Before 7.6.7 the derived value was
    http://dspace-angular:4000/, because compose pins DSPACE_UI_HOST: dspace-angular. It was already
    wrong, in a different way.
  • The "yarn install will drift off the pin" warning was wrong. Tested on a clean tree with no
    --frozen-lockfile: yarn v1 reuses the satisfying lock entry and installs 2.17.5, lock unchanged.
  • CI is "4 pass + 1 skipping" plus one pre-existing hard failure: issue_opened.yml is a 0-byte
    workflow file, identical to origin/dtq-dev.
  • Namespace caveat, now documented: DSPACE_UI_NAMESPACE must match the path in the URL. They are
    independent settings with no cross-check, and the legacy-bitstream redirect builds its target from
    nameSpace + route resolved against baseUrl — a namespaced URL with the namespace left at /
    produces a 404 on every legacy citation link.
  • Reviewers confirmed a wrong ui.baseUrl is not a Shibboleth security issue: the FE builds that
    redirect from window.origin.

Known and not fixed

  • docker-compose-dist.yml keeps its :-http://localhost:4000 default — correct for its own
    demo-preview use case, but inconsistent with the main compose.
  • Three vanilla dependency bumps were dropped by the lockfile merge (postcss 8.5.14→8.5.6,
    @babel/runtime 7.28.6→7.28.4, an extra express 4.22.1). No CVE maps to them; reconciling
    yarn.lock risks disturbing the sanitize-html resolution, so it is left for a follow-up.
  • Retracted: the claim that three info.accessibility-settings.liveRegionTimeOut.* keys are missing
    from cs.json5 and fall back to English was wrong. All three are present and Czech-translated
    (cs.json5:2946,2949,2952), added by PR UFAL/Sync translation messages and their structure with vanilla #956 long before this branch. Nothing falls back.
  • Because docker-compose.yml now hard-fails without UI_URL/DSPACE_UI_BASEURL while every other
    compose file defaults it, the deploy hosts' env files (/opt/dspace-envs/.env.dspace.dev-5,
    .env.dspace.imported.dev-5) must be checked to actually define it — they were never obliged to.
    This cannot be verified from the repository.

alanorth and others added 30 commits September 10, 2025 19:48
If `environment.ui.host` is Falsy, then we attempt to fall back to
a host value of '/', which is invalid. I think that, if a user has
messed up their config so much that defaults in our configuration
interface don't work, then we should actually fail here.

(cherry picked from commit f622d58)
If a user has messed up their config so much that the fallbacks in
our default configuration interface don't work then we should just
fail here.

(cherry picked from commit 6c09677)
[Port dspace-7_x] src/themes/dspace: rework banner image
[Port dspace-7_x] server.ts: remove port and host fallbacks in run
…pace-7_x/testing-c9201e7a88

Bump cypress-axe from 1.6.0 to 1.7.0 in the testing group
…pace-7_x/isbot-5.1.30

Bump isbot from 5.1.29 to 5.1.30
…pace-7_x/sass-2e0f0fb0cc

Bump sass from 1.89.2 to 1.92.1 in the sass group
…pace-7_x/babel/runtime-7.28.4

Bump @babel/runtime from 7.28.2 to 7.28.4
…pace-7_x/core-js-3.45.1

Bump core-js from 3.44.0 to 3.45.1
When adding mappings in the item mapper we should use the save icon
rather than the trash icon!
- Track head links in a Map, because Set doesn't deduplicate them properly
- Make ServerHashedFileMapping independent of ThemeConfig
- Make theme pre-fetching configurable (e.g. only prefetch the main theme CSS, but leave route-based theme CSS lazy)
….6_CLEAN' into cache-bust-dynamic-configuration-7.6
…rough an innerHTML attribute or not to properly escape them
…icon-7x

 [Port dspace-7_x] src/app: use correct icon in item mapper
…ations

[WIP] Added czech translations to `cs.json5`
…ring

Client side rendering (CSR) ignores `nameSpace` configuration causing broken resource loading
…2284_fix-issue4500-hierarchical-browse-pagination-7_x'
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.45.1 to 3.46.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.46.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-version: 3.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [axios](https://github.com/axios/axios) from 1.11.0 to 1.13.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.11.0...v1.13.1)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the sass group with 1 update: [sass](https://github.com/sass/dart-sass).


Updates `sass` from 1.92.1 to 1.93.2
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](sass/dart-sass@1.92.1...1.93.2)

---
updated-dependencies:
- dependency-name: sass
  dependency-version: 1.93.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: sass
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [isbot](https://github.com/omrilotan/isbot) from 5.1.30 to 5.1.31.
- [Changelog](https://github.com/omrilotan/isbot/blob/main/CHANGELOG.md)
- [Commits](omrilotan/isbot@v5.1.30...v5.1.31)

---
updated-dependencies:
- dependency-name: isbot
  dependency-version: 5.1.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Consider the language set in the users profile when setting it on page load. Also match languages case-insensitive. Updated tests
[Port dspace-7_x] Removes references to X.509 authentication method
kanasznagyzoltan and others added 24 commits May 14, 2026 17:27
[Port dspace-7_x] Make CI workflow fork-friendly (skip GHCR login and Codecov on forks)
[Port dspace-7_x] fix DSpace#5544: enlarge dropdown for external source import
…e alerts across views

(cherry picked from commit e44f9cf)
[Port dspace-7_x] Fix DSpace#5332: Fix inconsistent rendering of <em> tag in system-wide aler…
[Port dspace-7_x] Fix DSpace#5672: resolve health check issue with response handling
Bumps the testing group with 1 update: [axe-core](https://github.com/dequelabs/axe-core).


Updates `axe-core` from 4.11.3 to 4.11.4
- [Release notes](https://github.com/dequelabs/axe-core/releases)
- [Changelog](https://github.com/dequelabs/axe-core/blob/develop/CHANGELOG.md)
- [Commits](dequelabs/axe-core@v4.11.3...v4.11.4)

---
updated-dependencies:
- dependency-name: axe-core
  dependency-version: 4.11.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: testing
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the postcss group with 1 update: [postcss](https://github.com/postcss/postcss).


Updates `postcss` from 8.5.12 to 8.5.14
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.12...8.5.14)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: postcss
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [sanitize-html](https://github.com/apostrophecms/apostrophe/tree/HEAD/packages/sanitize-html) from 2.17.3 to 2.17.4.
- [Changelog](https://github.com/apostrophecms/apostrophe/blob/main/packages/sanitize-html/CHANGELOG.md)
- [Commits](https://github.com/apostrophecms/apostrophe/commits/HEAD/packages/sanitize-html)

---
updated-dependencies:
- dependency-name: sanitize-html
  dependency-version: 2.17.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [express](https://github.com/expressjs/express) from 4.22.1 to 4.22.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/v4.22.2/History.md)
- [Commits](expressjs/express@v4.22.1...v4.22.2)

---
updated-dependencies:
- dependency-name: express
  dependency-version: 4.22.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…y while maintaining 'DELETE' display in UI through getActionDisplayLabel() method. Updated form dropdown to show 'DELETE' label. Added unit tests for action display label handling.
…-7_x

[Port dspace-7_x] :Backport change DELETE to OBSOLETE (DELETE) and update view table (DSpace#4484)
[Port dspace-7_x] Fix browse-by pages sending unnecessary request to author index
…pace-7_x/express-4.22.2

Bump express from 4.22.1 to 4.22.2
…pace-7_x/postcss-06160b2e2d

Bump postcss from 8.5.12 to 8.5.14 in the postcss group
…pace-7_x/sanitize-html-2.17.4

Bump sanitize-html from 2.17.3 to 2.17.4
…pace-7_x/testing-a398129e23

Bump axe-core from 4.11.3 to 4.11.4 in the testing group
Applies the dspace-angular 7.6.5->7.6.7 delta onto the CLARIN fork dtq-dev
(head ac78637, incl. #1392) as a two-parent merge with merge-base dspace-7.6.5.
Resolves the 29 conflicting files per the section-4.2 recipes; regenerates
yarn.lock with classic Yarn 1.22 (v1; direct axios dropped, node-html-parser
added, ngx-mask pinned 13.1.15).

Out-of-marker / build-caught fixups (vanilla API changes breaking CLARIN callers):
- locale.service: vanilla changed getCurrentLanguageCode() to Observable<string>;
  reverted it (and setCurrentLanguageCode) to fork's sync string form while keeping
  vanilla's getLanguageCodeList(ignoreEPersonSettings) param (used by the interceptor).
- license-contract-page: getAuthorizedCollection gained a searchHref param -> pass
  'findSubmitAuthorized' (the fork's previous hardcoded value).

Validation: build:prod (SSR) OK, lint clean, check-circ-deps clean, frozen-lockfile no-op.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@milanmajchrak
milanmajchrak changed the base branch from dtq-dev to dtq-dev-767-base July 30, 2026 08:20
milanmajchrak and others added 2 commits July 30, 2026 12:14
- yarn.lock: sanitize-html 2.17.6 -> 2.17.4 (2.17.6 requires node >=22.12, CI runs 18/20)
  Also drops the orphaned htmlparser2@12 subgraph (htmlparser2, domelementtype,
  domhandler, domutils, entities, dom-serializer) that only 2.17.6 pulled in;
  htmlparser2 key restored to vanilla form "^10.1, ^10.1.0". package.json unchanged.
- locale.service.spec.ts + locale.interceptor.spec.ts: align with sync getCurrentLanguageCode
  (7 TS2345 errors made the whole karma bundle fail to load, so no test ran at all)
- locale.service.ts: drop now-dead subs/ngOnDestroy/OnDestroy left over by the sync revert

Validated on node 20.19.0: install/frozen-lockfile/lint/circ-deps/build:prod/test:headless
(5488 tests SUCCESS, 0 failed). frozen-lockfile engines gate additionally re-verified
on node 18.20.4 (both CI matrix legs).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2.17.4 was the wrong stopping point. The reason for not taking 2.17.6 is its
engines.node >=22.12.0 (CI runs 18.x and 20.x) - but 2.17.5 has no engines field
at all and still depends on htmlparser2 ^10.1.0, the version already hoisted in
this lockfile, so it was available at no cost and was overlooked.

2.17.5 carries real XSS hardening that has no GHSA advisory, so "no advisory is
patched in 2.17.5" was not a sound safety argument:
- allowedSchemesAppliedToAttributes grows from 3 to 20 entries, so a javascript:
  URL in formaction, action, data, xlink:href, poster and 12 others is now
  scheme-checked; 2.17.4 let those through
- the srcset check is extended to imagesrcset
- tagAllowed() guards are added to the raw-text passthrough branches, which is
  the code path of the critical GHSA-rpr9-rxv7-x643

Verified: yarn install resolves 2.17.5, htmlparser2 stays 10.1.0, no engines error
on node 20.19.0, --frozen-lockfile is "Already up-to-date", lint clean,
test:headless TOTAL: 5488 SUCCESS. The only source that uses sanitize-html is
markdown.pipe.ts; none of the 17 newly scheme-checked attributes appear in its
MathJax allowlist, and MathJax SVG output is byte-identical between 2.17.4 and
2.17.5. 2.17.6 remains blocked on the node bump.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
milanmajchrak and others added 2 commits August 3, 2026 12:23
7.6.7 stopped deriving `ui.baseUrl` from DSPACE_UI_HOST/PORT/SSL and hardcoded
`http://localhost:4000` instead, so those vars are now silently ignored for this
purpose. Legacy `/bitstream/handle/...` redirects and the robots.txt Sitemap would
point at localhost with no error in the log.

`docker/docker-compose.yml` now requires DSPACE_UI_BASEURL with no default, so a
deploy that forgets it fails loudly. It has to be added to each instance's env file
(deploy.yml passes `--env-file /opt/dspace-envs/...`). CI is unaffected -
docker-compose-ci.yml has no dspace-angular service.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…UI_URL

Two problems an independent review found in the previous two commits.

**D7 was not implemented as decided.** The instruction was to prefer vanilla unless
it breaks CLARIN functionality. `locale.service.ts` on the base branch is byte-identical
to `dspace-7.6.5`, i.e. the fork never customised it and a 3-way merge could not have
conflicted - yet the head carried a third blob with 7.6.5's logic. That silently dropped
vanilla's language-detection fix: the full Accept-Language q-list scan, case-insensitive
matching (`DE` and `en-GB` fell through to defaultLanguage), and "don't write an
auto-detected language to the cookie". Worse, the specs had been rewritten to assert the
old behaviour and vanilla's case-insensitivity test deleted, so green CI proved nothing.

`locale.service.ts`, `locale.service.spec.ts` and `locale.interceptor.spec.ts` are now
byte-identical to `dspace-7.6.7` again (verified with `git diff --numstat`).

The reason for the original revert was real: five CLARIN call sites are synchronous
template getters, and vanilla's `getCurrentLanguageCode()` has to be an Observable because
`getLanguageCodeList()` depends on the auth state. But those call sites do not want language
*negotiation* - they want the language the UI is currently rendering in. So they now use a
new, additive `getCurrentLanguageCodeSync()`, and vanilla's method is untouched. The CLARIN
test lives in a separate `locale.service.clarin.spec.ts` so the upstream spec stays
byte-identical and does not re-conflict on the next merge.

**`DSPACE_UI_BASEURL` ignored an existing convention and would have bricked every deploy.**
`UI_URL` is already defined in `build-scripts/run/envs/*` and already feeds the backend's
`dspace.ui.url` via `docker-compose-rest.yml` and `cli.yml` - the same value `ui.baseUrl` is
documented to hold. Requiring a brand-new variable with no default meant `start.sh`,
`deploy.yml` and every documented `docker/README.md` recipe would abort, and an override
compose file cannot rescue it because compose interpolates per file before merging.

`DSPACE_UI_BASEURL` now defaults to `UI_URL` and only fails when neither is set. Verified:

    envs/.default (UI_URL only)  -> DSPACE_UI_BASEURL: http://dev-5.pc
    neither set                  -> error: required variable UI_URL is missing a value
    DSPACE_UI_BASEURL explicit   -> wins over UI_URL

`envs/.local` gained `UI_URL`; `docker/README.md` now carries the requirement next to the
recipes that need it. Two corrections to the earlier rationale: the blast radius also
includes the Google Scholar `citation_pdf_url` / `citation_abstract_html_url` meta tags, and
the pre-upgrade derived value was `http://dspace-angular:4000/`, not a working public URL -
so this fixes a long-standing wrong value rather than a regression the upgrade introduced.
The namespace caveat is now documented: `DSPACE_UI_NAMESPACE` must match the path in the URL
or the legacy-bitstream redirect drops the prefix.

Tests: locale specs 21 SUCCESS (16 upstream incl. the restored case-insensitivity test, plus
5 new), header/clarin-license-info/html-content specs 9 SUCCESS, lint clean on all changed
files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.