Internal Admin

internal-client-v2 is Payability’s internal administration client: the Angular single-page application that internal staff use to run the business. Everything that is not self-service for a seller happens here — onboarding a supplier, underwriting them, pricing and approving an advance, configuring marketplace funding, releasing payment batches, approving balances, running reports, and managing the back-office configuration that drives all of it.

It is an internal tool, not a customer-facing product. There is no public sign-up, no marketing surface and no multi-tenant isolation inside the app: the audience is Payability employees, and authorisation is enforced by the backend against a per-user permission set.

This documentation describes the front end only. The business rules that matter for money movement — how a fee is actually charged, how a balance is computed, whether a payment clears — live in the backend services this app talks to. Where the front end owns a rule (offer pricing arithmetic, event-rule composition, form validation, guard logic), that is stated explicitly.

Start here

If you want to… Read

Understand what the product does in business terms

What the application does

Get productive in the codebase quickly

Orientation for new developers

Understand how the app is put together

Architectural overview

Find the business logic for a particular area

Business domains

Understand auth, permissions, flags, events

Platform concerns

Run, build, test or deploy it

Development and operations

Look up a route, action, endpoint or flag

Reference

A page-by-page index is in the documentation map. Domain vocabulary is defined in the glossary.

The shape of the system in one picture

                       ┌──────────────────────────────────────┐
   Internal staff ───► │  Internal Admin (this application)   │
   (Google SSO or      │  Angular {angular-version} SPA, hash routing │
    username/password) │  NgRx store, AG Grid, Material       │
                       └───┬──────────────┬───────────────┬───┘
                           │              │               │
              X-Session-Token header      │        postMessage
                           │              │               │
              ┌────────────▼───┐  ┌───────▼────────┐  ┌───▼──────────────┐
              │ Internal API   │  │ Satellite      │  │ EVA micro-front  │
              │ (database_v2)  │  │ services       │  │ end (iframes)    │
              │ suppliers,     │  │ actionstools,  │  │ supplier top bar,│
              │ payments,      │  │ eventlogger,   │  │ menu, contracts, │
              │ reports, fees, │  │ messaging,     │  │ onboarding views │
              │ perms, configs │  │ documents,     │  └──────────────────┘
              └────────────────┘  │ authtools,     │
                                  │ marketplace,   │
                                  │ taskmanager,   │
                                  │ uw-tool, s3    │
                                  └────────────────┘

The application is a thin, stateful client over many backends. There is no single API gateway: the environment configuration carries roughly a dozen base URLs, each service wrapper reads the one it needs from AppConfigService, and a single interceptor attaches the session token to every request. See the integration landscape for the full map and the endpoint reference for which service talks to which host.

What makes this codebase distinctive

Angular 12 with NgRx 4

The state layer predates createAction/createReducer and @ngrx/entity. Actions are hand-written classes with readonly type string constants, effects use the @Effect() decorator and this.actions$.ofType(…​). This is deliberate — see state management before adding store code.

Fractal module structure

Feature modules recurse: a module may contain model/, services/, store/ and sub-component folders, and a sub-component folder may contain the same. Scope determines placement — application-wide code in src/app/shared, module-wide code in that module’s shared/. See the module map.

Selective state, not total state

Only a handful of slices are in the store (auth, supplier, crm, layout, utils, global settings, marketplace, onboarding, underwriting, background reports, calculator, fetched requests). Most feature state is component-local. Do not add a store slice for something that does not need one.

Permission-driven navigation

Nearly every route carries an ngx-permissions clause, and the sidebar mirrors it with ngxPermissionsExcept / *ngxPermissionsOnly. Two permissions — REST_UW_ACCESS and ADVANCE_AUDITORS — act as broad *deny filters across the whole app. See authorisation.

Two generations of almost everything

Event rules v1 and v2, old and new search engines, supplier-underwriting and supplier-underwriting-beta, data-table / data-table-grid / data-table-ag-grid / pyb-ag-grid, b2b-document and pyb-documents. Migrations were started and not finished. Each doc page names which generation is current.

Micro-front-end seams

Parts of the supplier workspace are rendered by EVA, a separate front end embedded in iframes and driven by a typed postMessage protocol. See iframe messaging and EVA.

Scope and freshness

This component documents the state of the develop branch. Facts that change with the code — route tables, action names, endpoint lists, flag and permission catalogues — are collected in the reference module so that they can be re-derived in one place when the code moves.

Where a page states a rule, it cites the file that implements it. If the citation no longer matches the code, trust the code and fix the page.