Aman-Mittal commented on issue #377:
URL: 
https://github.com/apache/fineract-backoffice-ui/issues/377#issuecomment-5308037696

   ## Staying current with Fineract, and the Docker Hub question
   
   Answering the two engineering questions raised alongside this release.
   
   ### 1. Does the UI stay current with the head of Fineract main?
   
   **Today, yes — and this was verified rather than assumed.** The spec inside 
the running `apache/fineract:latest` container was extracted and diffed against 
the committed contract:
   
   ```
   committed public/api/fineract.json   info.version 1.16.0-SNAPSHOT | paths 
594 | operations 958
   spec inside apache/fineract:latest   info.version 1.16.0-SNAPSHOT | paths 
594 | operations 958
   operations in head but not committed:  0
   operations committed but gone from head: 0
   ```
   
   `.github/workflows/api-spec-sync.yml` is what keeps it that way: weekly, 
resolves `apache/fineract:latest` to a **digest**, short-circuits if the digest 
has not moved, otherwise reads the spec out of the image without booting 
Fineract, regenerates the client, writes a provenance record, and opens a PR. 
`permissions: {}` at workflow level. The real-backend E2E job also runs against 
`latest`, so behavioural drift is exercised on every PR, not just contract 
drift.
   
   Of the platform's 958 operations the UI calls **564 across 142 services**, 
pinned in `src/app/core/adapters/api/api-surface.json` and enforced by `npm run 
api:surface` in CI. Drift in either direction fails the build.
   
   **Three gaps worth closing:**
   
   | # | Check | Why |
   |---|---|---|
   | 1 | Nightly `E2E (real Fineract)` on `main` | Head-drift is only exercised 
when someone opens a PR. A quiet week runs nothing. |
   | 2 | Make the spec-sync compile-check failure loud in the PR body and job 
summary | Keep `continue-on-error` — an upstream removal must still open its PR 
— but a break should not read as green. |
   | 3 | Daily rather than weekly sync | The digest short-circuit already makes 
an unchanged run cost seconds. |
   
   ### 2. "The first release may need to be retrospective to 1.15"
   
   **This is the real gap, and nothing currently covers it.** Everything above 
validates against *head*, and the committed spec reports `1.16.0-SNAPSHOT`. 
Whether all 564 operations the UI calls exist in **1.15** is presently 
**unknown**.
   
   | # | Work | Why |
   |---|---|---|
   | 4 | `scripts/check-api-compatibility.mjs <spec>` — diff `api-surface.json` 
against a target Fineract spec, fail on any operation the UI calls that the 
target does not serve | The single most important unanswered question if 1.15 
is the target. `scripts/spec-diff-summary.mjs` already has most of the 
machinery. |
   | 5 | A compatibility-matrix E2E job running the `backend` project against a 
pinned `apache/fineract:1.15.0` | Contract compatibility is necessary but not 
sufficient; behaviour differs too. |
   | 6 | A supported-versions table in the README, generated from whichever 
versions the matrix actually runs | So a deployer can see what was tested 
rather than infer it. |
   
   **If 1.15 is the release target, item 4 should be green before the vote.**
   
   ### 3. Deploying alongside Fineract on Docker Hub
   
   The image **builds** — `docker build -f deploy/Dockerfile .` → exit 0, 107 
MB — but is not deployable as shipped. Running it:
   
   ```
   GET /                        → 200 text/html            (the SPA)
   GET /config.json             → {"fineractApiUrl":"/api/v1", …}
   GET /api/v1/authentication   → 200 text/html, 7546 bytes   ← the SPA shell, 
not Fineract
   ```
   
   `deploy/nginx.conf` has no `location /api/` proxy, so every API call falls 
through `try_files` to `index.html`. The alternative — the compose file setting 
an absolute cross-origin `FINERACT_API_URL` — is blocked by the CSP that same 
file serves (`connect-src 'self'`, confirmed in the response headers).
   
   Setting `FINERACT_API_URL` also reduces `config.json` from five keys to two:
   
   ```
   before: fineractApiUrl, defaultTenant, rbacEnabled, institutionType, 
developerToolsEnabled
   after:  fineractApiUrl, defaultTenant
   ```
   
   `ConfigService` merges over its defaults, so `rbacEnabled` still lands 
`true` — **this is not an RBAC bypass**, and that was checked in source rather 
than assumed. But `allowedApiOrigins` (which backs a blocking GA security 
gate), `institutionFeatures` and `nav` overrides become unconfigurable in a 
container.
   
   **In order, before anything is published:**
   
   | # | Work |
   |---|---|
   | 7 | Add the API proxy to `deploy/nginx.conf` so `fineractApiUrl: 
"/api/v1"` is same-origin and satisfies `connect-src 'self'` |
   | 8 | Point the compose file at a local Fineract service, not a third-party 
demo host |
   | 9 | `npm ci` in the Dockerfile; pin both base images by digest |
   | 10 | Let the entrypoint **merge** `config.json` rather than overwrite it |
   | 11 | A CI job that builds the image, runs it, and asserts `GET /api/v1/…` 
is proxied and not HTML |
   | 12 | `HEALTHCHECK`, non-root nginx, drop the obsolete `version: '3.8'` |
   | 13 | A publish workflow (tag → multi-arch build → provenance → Docker 
Hub), gated on the PMC vote |
   
   Item 11 is the one that matters most long-term: this audit found the proxy 
gap in ten minutes because it ran the container. CI never has.
   
   ### 4. On "the security setup is better than existing solutions"
   
   That claim needs a defensible basis, so here is the evidence, all verified 
in this audit:
   
   | Property | This application |
   |---|---|
   | Route-level permission enforcement | Yes — `permissionGuard` on protected 
routes, returning a real Access Denied page rather than a silent dashboard 
bounce |
   | Navigation/route drift prevention | Yes — a CI check that fails on 
disagreement and exits 1 rather than passing vacuously if it parses nothing |
   | Permission codes validated against the platform catalogue | Yes — 223/223 
real, checked against the live 699-code catalogue |
   | Two-factor authentication | Yes, with a dedicated E2E stack and a mail 
catcher |
   | CSP without `unsafe-eval` | Yes, shipped in `deploy/nginx.conf` |
   | API-origin allow-list for endpoint override | Yes — a blocking GA gate |
   | Authorization header restricted to the API origin | Yes — a blocking GA 
gate |
   | No sanitizer bypasses or raw HTML sinks | Yes — a blocking GA gate |
   | Production dependency vulnerabilities | 0 |
   | Published threat model | 61 KB, in-repo |
   | Signed-commit enforcement on PRs | Yes |
   | Backend refusal asserted in tests | Yes — E2E confirms Fineract itself 
refuses the restricted user's operation |
   
   The honest framing for a vote is **"defence-in-depth the previous UI did not 
have, with Fineract Core still the authoritative boundary"** — not "more 
secure". A frontend cannot be the security boundary, and `DOCS/RBAC.md`, 
`security.md` and the guard's own doc comment are already careful to say so. 
That framing should not be softened to make the release read better.


-- 
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