mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 23:28:11 +00:00
feat(eims): take the source system from the access token
MoR stamps systemNumber and systemType into the access token it issues for the authenticating credentials, which makes the token the authority on them. Registration now reads both from there instead of from configuration, so the SourceSystem block cannot drift from what the gateway believes we are. EimsAuthService decodes the token payload after login, requires both claims to be non-empty, and exposes them through getSessionContext(). The token is decoded but never verified -- it is MoR's, signed with MoR's key -- and is kept out of the log line, which names only the system it identified. EIMS_SYSTEM_NUMBER and EIMS_SYSTEM_TYPE become optional expectations rather than inputs: when set they are compared against the claims and a mismatch fails fast, so neither side silently wins. Neither is required to register any more. Registration and manual resolution both resolve the session before touching the state row, which is keyed by the system number: a login failure now costs nothing because no counter has been reserved yet. Test fixtures move to eims-test-fixtures.ts. They previously lived in eims-auth.service.spec.ts, which made jest execute that suite again inside every importing spec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { BadRequestException } from "@nestjs/common";
|
||||
import { EimsConfig } from "../../config/eims.config";
|
||||
import { EimsSessionContext } from "./eims-auth.service";
|
||||
import {
|
||||
EimsMapperContext,
|
||||
EimsMapperLine,
|
||||
@@ -21,10 +22,10 @@ interface RequiredSpec {
|
||||
value: string | number | null | undefined;
|
||||
}
|
||||
|
||||
const REQUIRED = (invoice: EimsConfig["invoice"], tin: string, systemNumber: string, systemType: string): RequiredSpec[] => [
|
||||
// `systemNumber` / `systemType` are absent by design: they come from the access token, which is
|
||||
// MoR's own statement of who we are. See EimsAuthService.getSessionContext.
|
||||
const REQUIRED = (invoice: EimsConfig["invoice"], tin: string): RequiredSpec[] => [
|
||||
{ env: "EIMS_TIN", value: tin },
|
||||
{ env: "EIMS_SYSTEM_NUMBER", value: systemNumber },
|
||||
{ env: "EIMS_SYSTEM_TYPE", value: systemType },
|
||||
{ env: "EIMS_SELLER_LEGAL_NAME", value: invoice.sellerLegalName },
|
||||
{ env: "EIMS_SELLER_VAT_NUMBER", value: invoice.sellerVatNumber },
|
||||
{ env: "EIMS_SELLER_PHONE", value: invoice.sellerPhone },
|
||||
@@ -44,7 +45,7 @@ const REQUIRED = (invoice: EimsConfig["invoice"], tin: string, systemNumber: str
|
||||
|
||||
/** Throws naming every unset variable at once, so one round trip fixes the whole configuration. */
|
||||
export function assertEimsInvoiceConfig(config: EimsConfig): void {
|
||||
const missing = REQUIRED(config.invoice, config.tin, config.systemNumber, config.systemType)
|
||||
const missing = REQUIRED(config.invoice, config.tin)
|
||||
.filter(({ value }) => value === null || value === undefined || value === "")
|
||||
.map(({ env }) => env);
|
||||
|
||||
@@ -80,6 +81,8 @@ export interface EimsContextInput {
|
||||
documentNumber: string;
|
||||
invoiceCounter: number;
|
||||
previousIrn: string | null;
|
||||
/** Source-system identity from the access token, never from configuration. */
|
||||
session: EimsSessionContext;
|
||||
/** Required when the invoice currency is not ETB. */
|
||||
exchangeRate?: number | null;
|
||||
}
|
||||
@@ -92,8 +95,8 @@ export function buildEimsContext(config: EimsConfig, input: EimsContextInput): E
|
||||
const exciseTaxValue = invoice.exciseTaxValue ?? 0;
|
||||
|
||||
return {
|
||||
systemNumber: config.systemNumber,
|
||||
systemType: config.systemType,
|
||||
systemNumber: input.session.systemNumber,
|
||||
systemType: input.session.systemType,
|
||||
documentNumber: input.documentNumber,
|
||||
invoiceCounter: input.invoiceCounter,
|
||||
previousIrn: input.previousIrn,
|
||||
|
||||
Reference in New Issue
Block a user