Aman-Mittal opened a new pull request, #361:
URL: https://github.com/apache/fineract-backoffice-ui/pull/361

   The UI loaded Inter from `fonts.googleapis.com` via a `<link>` in 
`src/index.html`. This removes that dependency and renders in the platform's 
own interface font instead.
   
   No dependency is added: `package.json` and `package-lock.json` are 
byte-identical to `main`.
   
   ## Why
   
   Three problems, in increasing order of how long each went unnoticed.
   
   **The production build depended on a network fetch.** Angular's font 
inlining downloads that stylesheet during a production build and inlines the 
`@font-face` rules. When the host is unreachable the build does not degrade — 
it fails:
   
   ```
   ✘ Inlining of fonts failed. An error has occurred while retrieving
     
https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap
     over the internet.
   ```
   
   An ASF release has to be buildable from its source package. This one could 
not be built without reaching a third-party service.
   
   **The fetched bytes were not pinned.** Every other dependency is locked by 
integrity hash in `package-lock.json`. A `css2?family=Inter:wght@…` URL pins 
nothing, so two builds of the same commit could embed different bytes with 
nothing recording the difference.
   
   **The font never actually loaded in our own container.** `deploy/nginx.conf` 
sets `font-src 'self' data:`, so every request the built page made to 
`fonts.gstatic.com` was blocked by our own CSP. The deployed UI has always 
rendered in the fallback stack — which is why removing Inter changes nothing a 
user of the image sees.
   
   ## Measured, not assumed
   
   Two Docker images built from `deploy/Dockerfile`, one per revision, driven 
in Chrome behind the identical production CSP:
   
   | | `main` | this branch |
   | --- | --- | --- |
   | Requests to `fonts.gstatic.com` | 35, all blocked | **0** |
   | CSP font violations | 35 | **0** |
   | Offline production build (`unshare -rn`) | **exit 1** — `Inlining of fonts 
failed` | **exit 0** |
   
   ## Why not self-host Inter
   
   Self-hosting from a pinned `@fontsource-variable/inter` was implemented and 
verified first, and it worked — the offline build passed and the hashed 
`.woff2` files served from our own origin, byte-identical (SHA-256) to what 
Google served.
   
   It was dropped because Inter is SIL OFL 1.1, which ASF policy classifies as 
[**Category B**](https://www.apache.org/legal/resolved.html): admissible in 
binary form in a convenience binary when labelled, and *not* admissible in a 
source release. `CONTRIBUTING.md` already states the same rule — "New runtime 
dependencies must be **Apache Category A** compatible" — and CI enforces it: 
`license-checker --onlyAllow 
"MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;0BSD"` rejects `OFL-1.1` outright.
   
   Satisfiable, but it costs a licence file, a README label, a `.rat-excludes` 
entry, a Dockerfile change and an `OFL-1.1` exception in that allow-list — for 
a typeface users of the container have never actually seen. For a first release 
that is a poor trade. `DOCS/FONTS.md` records the verified route back if a 
later release wants Inter.
   
   ## The change
   
   - `src/index.html` — removed the stylesheet link and both Google 
`preconnect` hints.
   - `src/styles.scss` — `system-ui, -apple-system, BlinkMacSystemFont, 'Segoe 
UI', Roboto, 'Helvetica Neue', Arial, sans-serif`. `system-ui` leads so Linux 
and Android resolve their real UI font rather than falling through to bare 
`sans-serif`, as the old stack did.
   - `scripts/ga-check.mjs` — new `external-fonts` gate so this cannot silently 
return. It scans `src/`, `public/`, `projects/`, `deploy/`, `angular.json` 
**and a built `dist/`** — the artifact matters as much as the source, because 
the build itself baked the dependency into the output. It matches only 
scheme-qualified or protocol-relative references, so prose naming the hosts 
does not trip it. Negative-tested by reinserting a `<link>`.
   - `DOCS/FONTS.md`, `DOCS/CI_CHECKS.md`, `README.md`, `.rat-excludes`, 
`audit/` — documentation, the gate's entry in the checks table, and the audit 
this came from.
   
   `NOTICE`, `deploy/nginx.conf` and the `license-checker` allow-list are all 
untouched. The CSP is not weakened. No `.woff2` is committed.
   
   ## Verification
   
   Online and offline production builds, 952/952 unit tests, `lint`, HTML lint, 
`format:check`, `check-license.sh`, Apache RAT (667 approved, 0 unapproved), 
`license-checker` against the unchanged allow-list, and the new `ga:check` 
gate. `ga:check`'s two other failures (`api-surface`, `adapter-boundary`) are 
identical on `main` and untouched here.
   
   One detail worth knowing for future edits: **Angular preserves HTML comments 
into the built `index.html`**. An explanatory comment naming the host leaked it 
into the artifact, so the comment now deliberately names no external host.
   
   ## Related
   
   Verification of this change surfaced two unrelated CSP defects that also 
reproduce on `main` — the critical-CSS `onload` and the native-federation 
`blob:` module are both blocked by `script-src 'self'`. Filed separately as 
#360 rather than mixed in here.
   
   Note there was no pre-existing tracking issue for the font work itself; the 
analysis lives in `audit/GOOGLE-FONTS-ASF-AUDIT.md`, added in this PR. Happy to 
open one if the convention requires it.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to