Le nœud de plateau et les machines
À lire d’abord
- Les machines sont prévues jusqu’à ce que l’une soit raccordée. La voie machines est construite et contractée, et seul du logiciel l’a jamais pilotée.
- Le manuel de référence de NCR pour ces machines n’a pas été lu. Toute valeur de protocole que porte l’échafaudage est la lecture que fait le Laboratoire de descriptions de NDC en circulation publique, consignée comme hypothèses A-46 à A-48 et redéfinissable machine par machine.
- L’adresse du lien est un espace réservé. Rien n’y écoute aujourd’hui, et aucun écouteur n’est déployé où que ce soit.
Ce que ceci est. Le Lab dispose de cinq machines NCR Atleos sur son plateau. Ce document
indique comment elles sont raccordées à la Simulation d'Écosystème Financier Virtuel, ce que
l'on ignore encore à leur sujet, et l'ordre dans lequel les travaux se déroulent.
Ce que ceci n'est pas. Ce n'est pas un exposé du fonctionnement d'un NCR Atleos. **Le manuel
de référence de NCR pour ces machines n'a pas été lu**, aucun document NCR n'a été consulté, et
chaque valeur de protocole que porte l'échafaudage est la lecture que fait le Lab de descriptions
de NDC circulant publiquement - consignées comme hypothèses A-46, A-47 et A-48 dans
[../spec/assumptions.md](../spec/assumptions.md) et redéfinissables, machine par machine, depuis
nodes/floor/<machine>.yaml. Rien ici ne doit être pris comme décrivant ce que les machines du
plateau font réellement tant que l'inventaire ci-dessous n'est pas fait.
Pourquoi un nœud de plateau existe
Un véritable terminal libre-service NCR ne décide de rien. Ses tables d'états disent *« dans cet
état, envoie une demande de transaction et attends »*, et ce qui se passe ensuite - quel écran,
quelle action de périphérique, combien sort des cassettes - est décidé par un hôte qui possède
ces écrans et répond en NDC (NCR Direct Connect), sur un lien TCP.
L'écosystème simulé vit sur Cloud Run, et Cloud Run ne peut pas accepter de TCP brut. Un
service Cloud Run s'atteint en HTTP(S) à travers le front end de Google sur l'unique port que
déclare le conteneur ; il n'y a pas de second écouteur auquel une machine puisse ouvrir une
socket, et rien dans la configuration du service ne peut en publier un. Le même paragraphe figure
déjà dans [../deploy/README.md](../deploy/README.md) à propos de l'écouteur ISO 8583, pour la
même raison.
Le Lab exécute donc la même image deux fois :
| Où | Ce que c'est | |
|---|---|---|
| La passerelle cloud | Cloud Run, ecosystem-gateway | HTTP, la console, toutes les voies, le monde de chaque équipe. Aucun écouteur TCP, et aucun n'est configuré. |
| Le nœud de plateau | un petit PC sur le LAN du Lab, sur le segment propre aux machines | FLOOR_NODE=1. Tient les ports TCP NDC et ISO 8583 que les machines composent, et transmet ce qu'elles demandent à la voie machines du cloud avec sa propre clé d'équipe. |
Le nœud de plateau est un participant du monde cloud, pas un second monde. Il ne tient aucun
registre, ne règle rien, et ne détient aucun état qu'un redémarrage perdrait, hormis le journal
du jour qu'il n'a pas encore remis. Tout ce qu'une machine demande est répondu par le switch
simulé dans le cloud, via /v1/atm/**, exactement comme le serait une intégration appelant ces
points de terminaison depuis un ordinateur portable. Le nœud de plateau ajoute un protocole,
pas une capacité.
La liste de recherche
Rien de ce qui suit n'est encore connu. Chaque ligne est une question avec un responsable
(Carlos), et chacune bloque quelque chose de précis - raison pour laquelle la liste est un
tableau et non un souhait.
| # | À découvrir | Ce que cela bloque |
|---|---|---|
| 1 | Modèle exact de chacune des cinq machines, et la version logicielle qui s'y trouve. Connu (2026-09-06) : le modèle phare est un NCR Atleos SelfServ 62 (recycleur de billets de hall intérieur sur le Scalable Recycler, écran tactile de 15 pouces, panneau supérieur de 18,5 pouces) exécutant NCR Atleos NDC Enterprise sur Windows 11 ; NCR présente NDC Enterprise comme le successeur multi-fournisseurs d'Advance NDC. Restent en suspens : les quatre autres modèles, et la version de NDC Enterprise sur chacun | tout ; on ne peut écrire un profil pour une machine que personne n'a identifiée |
| 2 | La version de NDC que parle le logiciel, et la version de XFS en dessous | tout le dialecte : le tramage, les classes de messages, l'ordre des champs (A-46, A-47) |
| 3 | Le manuel de référence de ce modèle et de cette version | remplace chaque valeur supposée dans packages/ndc-host/src/dialect.ts par une valeur lue |
| 4 | L'accès superviseur - le mode, l'identifiant, et qui le détient | la lecture de la configuration, du journal et des compteurs sur la machine, tout simplement |
| 5 | L'état des clés EPP - clés chargées, effacées, ou jamais chargées ; et si le Lab peut charger les siennes | la puce et le PIN, étape quatre. Rien avant cela n'a besoin d'une clé, raison pour laquelle rien avant cela n'attend |
| 6 | Les cartes : ce qui existe, et si le Lab peut embosser ou encoder les siennes dans la plage de BIN du Lab commençant par 9 | les flux avec carte présente. Le préfixe de PAN du Lab est délibérément hors des plages attribuées |
| 7 | Les clés d'AC pour la puce - quelles clés publiques d'autorité de certification les machines détiennent, et si des clés de test du Lab peuvent être chargées | EMV, étape quatre |
| 8 | Le mode test espèces - s'il existe sur ces machines et comment on y entre | distribuer sans faire circuler de vrais billets, étape trois |
| 9 | Le journal électronique - son format, où il est conservé, et comment on le relève sur la machine | remplace la ligne de journal du Lab (A-48) par celle de la machine |
| 11 | Qui possède les écrans et le flux. La page de NCR dit que NDC Enterprise permet à un exploitant de « gérer le flux transactionnel et l'interface utilisateur via le serveur d'entreprise ». Savoir si ce serveur est installé sur les machines du Lab, et si l'hôte (le nœud de plateau) télécharge encore les tables d'états et les écrans à la manière du NDC classique ou si c'est le serveur d'entreprise qui le fait, détermine quelle part du rôle de données de personnalisation de l'hôte nous revient | les messages de données de personnalisation de l'hôte (A-46) ; possiblement tout l'équilibre entre l'hôte et le serveur d'entreprise |
| 10 | Le VLAN - sur quel segment sont les machines, quoi d'autre peut l'atteindre, et si le nœud de plateau peut être la seule route de sortie | la frontière de sécurité de tout le dispositif. Voir ci-dessous |
Le VLAN est la frontière de sécurité, et c'est une décision
Il n'y a aucun identifiant sur le lien NDC, et cela est énoncé plutôt qu'omis. Un terminal
NDC n'a aucun champ où porter une clé d'équipe et aucune notion de présentation d'identifiant ;
un écouteur qui en exigerait un serait donc un écouteur auquel aucune machine ne peut parler.
Ce qui protège le lien, c'est le réseau sur lequel il se trouve. Les machines et le nœud de
plateau sont sur un VLAN qui leur est propre ; le nœud de plateau est la seule chose de ce
VLAN qui puisse atteindre Internet ; et la clé d'équipe réside sur le nœud de plateau, est
présentée par le nœud de plateau à la voie cloud, et ne circule jamais sur le lien machine, dans
un sens comme dans l'autre. Tout ce qui peut atteindre le port NDC peut piloter les écrans d'une
machine ; la réponse à « qui peut atteindre le port ? » est donc « les machines, et rien d'autre ».
Sur tout lien qui quitte le plateau, définissez NDC_TLS_CERT et NDC_TLS_KEY (et la paire
ISO 8583 à côté). Le TCP en clair est la valeur par défaut parce que le matériel de plateau ne
peut souvent pas faire mieux et qu'un écouteur qui refuse la machine n'est pas un écouteur.
Les ressources dont le Lab dispose déjà
Des rendus et animations 3D du SelfServ 62, un modèle Blender de celui-ci et des photographies réalistes existent et peuvent être fournis sur demande (Carlos, 2026-09-06). Ils ne sont pas dans ce dépôt. Ils servent les films, la page publique de simulation et une répétition de l'agencement physique du plateau ; ils ne sont pas nécessaires à l'hôte, qui ne voit jamais que les messages de la machine.
Les quatre étapes
Le rail et le NDC voyagent sur le même nœud de plateau. Une seule machine, une seule clé
d'équipe, deux ports : NDC_TCP_PORT pour les machines qui parlent NDC et ISO8583_TCP_PORT
pour une machine ou un TPE du même plateau qui parle ISO 8583 à la place. Ce n'est pas une
commodité, c'est le dispositif — les deux écouteurs ont besoin de TCP brut, Cloud Run n'en porte
aucun, et une seconde machine signifierait une seconde clé d'équipe, un second journal à
rapprocher et deux endroits où se tromper de VLAN. La moitié ISO 8583 a son propre profil
([../spec/iso8583-wire.md](../spec/iso8583-wire.md)), son propre sign-on et son propre pack de
conformité (npm run wire:conformance) ; tout ce qui suit à propos du VLAN, du fichier de clé et
des recettes de service s'y applique mot pour mot. Le même appariement est ce que monte la recette
Compute Engine de [../deploy/README.md](../deploy/README.md) lorsque le lien doit quitter le
plateau.
1. Inventaire. Traiter la liste ci-dessus, machine par machine, et écrire ce qui est trouvé
dans nodes/floor/<machine>.yaml - le bloc de dialecte pour ce que dit le manuel, la liste
pending pour ce qui reste ouvert. Aucune machine n'est mise sur le réseau à cette étape.
2. Nœud de plateau et hôte, pilotés par l'ATM virtuel et le switch virtuel. *(C'est ce qui
existe aujourd'hui.)* Le nœud de plateau tourne, les deux écouteurs sont actifs, et chacun est
sollicité par un double de test en forme de client qui compose une vraie socket et envoie de
vraies trames : NDC par packages/ndc-host/test/virtual-atm.ts - qui exécute l'identifiant de
fonction qu'on lui donne et en rend compte - et ISO 8583 par
packages/iso8583-wire/test/virtual-switch.ts, qui fait le sign-on, autorise, annule, retire
avec une carte et sans, et se voit répondre par le monde même dont répondent les voies REST. Les
deux sont éprouvés avant qu'une machine n'existe, ce qui est la seule façon d'arriver à l'étape
trois avec quelque chose qui vaille la peine d'être branché.
3. La première transaction sans espèces, sur UNE machine. Une machine, sur le VLAN, composant
le nœud de plateau. Consultation de solde uniquement : elle lit un compte, imprime un
montant, ne fait rien circuler et ne distribue rien. C'est la transaction la plus sûre qui soit
et la bonne première chose à exécuter sur une machine dont l'accès superviseur et le journal
viennent tout juste d'être compris. Ce que l'on éprouve ici, c'est le lien et le dialecte, pas
l'écosystème - l'écosystème répond à ces opérations en REST depuis des mois.
4a. Retrait sans carte avec billets de test. Le code à usage unique remis au téléphone du
titulaire est saisi sur la machine, le switch consomme l'ordre exactement une fois, et les
billets sortent - en mode test espèces si les machines en disposent, et avec des billets de
test dans le cas contraire. Pas de carte, pas de PIN, pas d'EMV, ce qui rend l'opération
exécutable avant qu'une seule clé ne soit chargée. Le journal électronique est relevé sur la
machine à la fin de l'exécution et rapproché via POST /v1/atm/journal.
4b. Puce et PIN, après chargement des clés. Seulement une fois les points 5, 6 et 7 de la
liste réglés. Cela requiert un EPP avec des clés, des cartes dans la plage de BIN du Lab, des
clés d'AC que les machines acceptent, et un dialecte qui a été lu plutôt que supposé. Rien
dans l'échafaudage ne calcule aujourd'hui de bloc PIN, ne détient de clé ni ne vérifie de
certificat, et rien ne devrait le faire avant cette étape.
Exécuter un nœud de plateau
Le nœud de plateau est l'image ordinaire avec un environnement de nœud de plateau. Il ne
nécessite ni build propre ni branche de code.
docker run -d --name finlab-floor \
--restart unless-stopped \
-p 8583:8583 -p 9100:9100 -p 8787:8787 \
-e FLOOR_NODE=1 \
-e NDC_TCP_PORT=9100 \
-e ISO8583_TCP_PORT=8583 \
-e CLOUD_GATEWAY_URL=https://ecosystem.financial \
-e FLOOR_TEAM_KEY_FILE=/run/secrets/floor-team-key \
-v /etc/finlab/floor-team-key:/run/secrets/floor-team-key:ro \
-v /etc/finlab/nodes/floor:/app/nodes/floor:ro \
ecosystem-gateway:latest
L'environnement
| Variable | Défaut | Ce que c'est |
|---|---|---|
FLOOR_NODE | vide | 1 active le mode nœud de plateau. Vide signifie que ce processus n'est pas un nœud de plateau, ce qu'est chaque instance cloud |
NDC_TCP_PORT | (requis en mode plateau) | le port que les machines composent pour NDC |
NDC_TCP_HOST | 0.0.0.0 | l'interface sur laquelle l'écouteur se lie |
CLOUD_GATEWAY_URL | (requis en mode plateau) | la passerelle cloud à laquelle les opérations machines sont transmises, p. ex. https://ecosystem.financial |
FLOOR_TEAM_KEY_FILE | vide | un fichier contenant la clé d'équipe du plateau. Préférable : une variable d'environnement est lisible par tout ce qui peut lister le processus, et un nœud de plateau se trouve là où quelqu'un a un accès physique |
FLOOR_TEAM_KEY | vide | la même clé dans l'environnement, quand un fichier n'est pas praticable. L'une des deux est requise |
FLOOR_NETWORK_ID | atm-network | l'identifiant de l'administrateur du réseau ATM dans le monde cloud, pour l'unique opération pour laquelle la voie machines ne nomme pas de route |
FLOOR_PROFILES | nodes/floor | l'emplacement d'où sont lus les profils de machines |
FLOOR_UNKNOWN_MACHINE | refuse | ce que reçoit une machine dont le LUNO ne figure dans aucun profil. refuse ferme la connexion - le bon défaut sur un plateau. default parle le dialecte par défaut du Lab, ce que veut un banc de test |
FLOOR_TIMEOUT_MS | 15000 | avant qu'il ne soit dit à une machine que l'hôte n'a pas pu atteindre son monde |
NDC_MAX_CONNECTIONS | 16 | machines tenues simultanément ; une de plus est refusée au niveau de la socket plutôt que mise en file |
NDC_IDLE_TIMEOUT_SECONDS | 300 | silence avant que l'écouteur ne ferme une connexion |
NDC_TLS_CERT / NDC_TLS_KEY | vide | chemins PEM. Les deux ou aucun : l'un sans l'autre empêche le nœud de plateau de démarrer plutôt que de lancer silencieusement un écouteur en clair que quelqu'un croyait chiffré |
ISO8583_TCP_PORT | vide | l'écouteur ISO 8583, pour une machine ou un TPE du même plateau qui le parle à la place. Lu par la passerelle elle-même ; voir [../deploy/README.md](../deploy/README.md) |
**Un nœud de plateau démarré sans clé, ou sans passerelle à laquelle transmettre, refuse de
démarrer.** C'est la bonne sévérité : une machine qui accepte la socket d'un automate puis fait
échouer chaque transaction est pire, pour la personne devant l'automate, qu'une machine qui n'a
jamais répondu.
En service systemd (PC de plateau sous Linux)
/etc/systemd/system/finlab-floor.service :
[Unit]
Description=FinLab floor node - NDC and ISO 8583 listeners for the Lab machines
After=network-online.target docker.service
Requires=docker.service
[Service]
Type=simple
Restart=always
RestartSec=5
# the key is a file the service user can read and nothing else can: 0400, owned by root
ExecStartPre=-/usr/bin/docker rm -f finlab-floor
ExecStart=/usr/bin/docker run --rm --name finlab-floor \
-p 9100:9100 -p 8583:8583 -p 8787:8787 \
-e FLOOR_NODE=1 -e NDC_TCP_PORT=9100 -e ISO8583_TCP_PORT=8583 \
-e CLOUD_GATEWAY_URL=https://ecosystem.financial \
-e FLOOR_TEAM_KEY_FILE=/run/secrets/floor-team-key \
-v /etc/finlab/floor-team-key:/run/secrets/floor-team-key:ro \
-v /etc/finlab/nodes/floor:/app/nodes/floor:ro \
ecosystem-gateway:latest
ExecStop=/usr/bin/docker stop finlab-floor
[Install]
WantedBy=multi-user.target
sudo install -m 0400 -o root -g root floor-team-key /etc/finlab/floor-team-key
sudo systemctl daemon-reload && sudo systemctl enable --now finlab-floor
journalctl -u finlab-floor -f
En service Windows (les machines sont sous Windows, et le PC de plateau peut l'être aussi)
Windows n'a pas d'enveloppe native « exécute ceci en tant que service » ; il faut donc en
utiliser une. Avec [NSSM](https://nssm.cc/) et Node 22 installés, en exécutant le dépôt
directement plutôt que le conteneur :
# the key, readable by the service account and nobody else
icacls C:\finlab\floor-team-key /inheritance:r /grant:r "NT SERVICE\finlab-floor:(R)"
nssm install finlab-floor "C:\Program Files\nodejs\npm.cmd" "run gateway"
nssm set finlab-floor AppDirectory C:\finlab\finlab-ecosystem
nssm set finlab-floor AppEnvironmentExtra ^
FLOOR_NODE=1 ^
NDC_TCP_PORT=9100 ^
ISO8583_TCP_PORT=8583 ^
CLOUD_GATEWAY_URL=https://ecosystem.financial ^
FLOOR_TEAM_KEY_FILE=C:\finlab\floor-team-key
nssm set finlab-floor AppStdout C:\finlab\logs\floor.log
nssm set finlab-floor AppStderr C:\finlab\logs\floor.log
nssm set finlab-floor Start SERVICE_AUTO_START
nssm start finlab-floor
Ouvrez les deux ports vers le VLAN des machines et vers rien d'autre :
New-NetFirewallRule -DisplayName "FinLab NDC" -Direction Inbound -Protocol TCP `
-LocalPort 9100 -RemoteAddress 10.20.30.0/24 -Action Allow
New-NetFirewallRule -DisplayName "FinLab ISO 8583" -Direction Inbound -Protocol TCP `
-LocalPort 8583 -RemoteAddress 10.20.30.0/24 -Action Allow
Les deux flux auxquels l'hôte répond aujourd'hui
Les deux sont projetés sur des opérations que le switch simulé publie déjà
(packages/atm-network/src/network.ts) et sur des points de terminaison que la voie machines
porte déjà (/v1/atm/**). L'hôte n'ajoute aucune capacité propre.
Consultation de solde
machine -> Transaction Request opcode buffer = the balance-inquiry code (A-47)
general-purpose buffer B = the account number
host -> /v1/atm/balance-inquiries { terminalId, issuerId, accountNumber }
host -> Transaction Reply function id = print only, screen = the balance screen,
the figure in the screen update and on the receipt
machine -> Solicited Status the reply was carried out
Rien ne circule et rien ne sort. L'identifiant de fonction est print only sur chaque chemin de
ce flux.
Retrait sans carte par code
(phone) -> /v1/atm/cardless/orders the holder's OWN institution mints the one-time code.
A machine never raises an order.
machine -> Transaction Request opcode buffer = the cardless-withdrawal code (A-47)
general-purpose buffer B = the one-time code
host -> /v1/atm/cardless/redemptions { terminalId, code }
host -> Transaction Reply approved: function id = dispense and print, and the
amount is THE ORDER'S, never the machine's
declined: function id = print only, the decline screen,
and the ISO 8583 DE039 on the receipt
machine -> Solicited Status the notes went out, or they did not
host -> a journal line, completed by that status
Quatre propriétés tiennent, et chacune est affirmée dans
packages/ndc-host/test/flows.test.ts :
- Toute requête reçoit une réponse. Une machine qui reçoit le silence n'imprime rien, expire, et apprend au client que les machines du Lab se bloquent.
- Un refus ne distribue rien. L'identifiant de fonction est déterminé par l'issue, et il n'existe aucun chemin par lequel une non-approbation atteigne dispense and print.
- Le montant est celui du switch. Ce que le client a saisi sur la machine est enregistré puis ignoré : l'ordre fait autorité, et une machine qui pourrait nommer son propre montant serait une machine qui pourrait se payer elle-même.
- Rien n'est distribué deux fois. Le switch consomme l'ordre avant d'autoriser, et l'hôte envoie la même réponse à un numéro de coordination répété plutôt que d'engager une seconde transaction - ce dont a réellement besoin une machine qui a manqué une réponse et a renvoyé sa requête.
Rapprocher le journal électronique
Chaque machine tient son propre relevé de la journée. Le switch tient le sien. Le rapprochement
consiste à trouver où ils divergent, et la direction intéressante est celle de la machine :
une ligne de journal dont le switch n'a aucune trace est un décaissement que personne ne réglera,
et c'est la forme d'une distribution survenue après la chute du lien. L'autre direction est
trouvée de toute façon, lorsque l'on compte les cassettes.
curl -sS https://ecosystem.financial/v1/atm/journal \
-H "x-lab-api-key: $FLOOR_TEAM_KEY" \
-H 'content-type: application/json' \
-d '{"journal":"2026-09-06T13:00:00.000Z|TERM-LAB-0001|cardless-withdrawal|ATM-atm-network-00001|200000|DOP|00|A"}'
Le rapport indique ce qui a été apparié (sur la référence, ou - pour une ligne sans référence -
sur le montant et le terminal), ce sur quoi une paire appariée diverge, ce qui n'est que dans le
journal, ce qui n'est qu'au switch, et les deux totaux avec leur différence.
Le format de ligne est propre au Lab, et c'est un espace réservé (hypothèse A-48). Le format
des journaux de ces machines est le point 9 de la liste. Lorsqu'il arrivera, un analyseur pour ce
format produira les mêmes objets JournalLine et rien en aval ne changera - ni l'appariement, ni
le rapport, ni le point de terminaison. C'est ce qui fait de ceci un échafaudage plutôt qu'une
supposition : la forme de la réponse est arrêtée et la lecture des octets ne l'est pas.
Où se trouve le code
packages/ndc-host/
├── src/dialect.ts the dialect table - READ THIS FIRST. A-46, A-47, all profile-driven
├── src/messages.ts the six NDC message families as objects
├── src/codec.ts bytes to messages and back, and the TCP stream framer
├── src/profile.ts nodes/floor/<machine>.yaml, and the dialect overrides in it
├── src/lane.ts the three switch operations, over HTTP or in-process
├── src/host.ts the state machine: the two flows above
├── src/server.ts the TCP listener, one host per connected machine
├── src/floor.ts FLOOR_NODE and the environment
├── src/journal.ts the journal line and the matcher
└── test/virtual-atm.ts the machine that does not exist, on a socket that does
Comment un switch partenaire se connecte, et le pack de conformité
Comment un switch partenaire se connecte
L'adresse est wire.ecosystem.financial:8583, et c'est un ESPACE RÉSERVÉ. Elle est écrite
ici pour qu'une intégration ait un nom à configurer et un seul endroit à changer lorsqu'un lien
sera effectivement monté. **Rien n'écoute dessus aujourd'hui, et aucun écouteur n'est déployé
nulle part.** Prétendre le contraire serait la fausse affirmation la plus facile à faire dans ce
dépôt et la plus coûteuse à avoir faite.
Pourquoi il n'y a encore rien à composer, sans détour :
L'écouteur a besoin d'un hôte capable de TCP, et la passerelle déployée n'en est pas un. La passerelle de l'écosystème tourne sur Cloud Run, que l'on atteint en HTTP(S) à travers le front end de Google sur l'unique port que déclare le conteneur ; il n'y a pas de second écouteur auquel un switch puisse ouvrir une socket, et aucune configuration qui en publie un. L'écouteur tourne donc là où le TCP brut est possible, ce qui signifie aujourd'hui l'un de deux endroits exactement : le nœud de plateau du Lab - cette même image sur un petit PC du segment réseau propre aux machines - ou une petite VM Compute Engine que le déployeur démarre, exécutant la même image avec
ISO8583_TCP_PORTdéfini. Les deux sont des recettes qu'une personne suit ; ni l'une ni l'autre ne tourne.docs/deploy/README.mdporte la recette de la VM sous forme de commandesgcloudrédigées, et elles n'ont pas été exécutées.
Ce que fait un partenaire, dans l'ordre :
- Demander une clé d'équipe. Le sign-on du rail prend une clé d'équipe - la même valeur que prennent les voies REST dans
x-lab-api-key, depuisFINLAB_API_KEYS. Une identité de service est un identifiant HTTP et n'est pas acceptée ici : sa portée s'exprime en méthodes HTTP et en voies, ce qu'une socket n'a pas. - Indiquer depuis quelles adresses le switch compose. Elles vont dans
ISO8583_ALLOWED_CIDRSsur l'écouteur. Un pair en dehors de cette liste est détruit au niveau de la socket sans réponse - pas de refus à lire, pas d'emplacement de connexion consommé, rien à en apprendre. Sur un VLAN de plateau la liste peut rester vide et le réseau fait la frontière ; sur tout lien qui quitte le plateau, elle n'est pas facultative. - Prendre le TLS.
ISO8583_TLS_CERTetISO8583_TLS_KEY, les deux ou aucun. Rappelez-vous ce qu'il y a dans le message : DE052 porte un PIN du Lab en clair - la simulation ne détient aucune clé et ne calcule aucun bloc PIN, et le §3 le dit dans le tableau - de sorte que le transport est la seule chose qui le protège. PIN simulé ou non, un lien qui en laisse fuir un enseigne une mauvaise habitude. Le certificat de plateau du Lab est auto-signé ; un partenaire devrait l'épingler plutôt que désactiver la vérification. - Exécuter le pack de conformité (§9) contre l'écouteur, depuis le réseau du switch, et conserver le rapport.
- Faire le sign-on, et le rester. Une connexion, un monde, un identifiant présenté une fois. Le lien est censé tenir la socket et faire de l'écho (
0800DE070301) plutôt que de se reconnecter à chaque transaction.
L'environnement que lit l'écouteur
Chacune de ces variables est lue par le processus passerelle qui tient le port. Vide signifie que
l'écouteur n'existe pas ; c'est ce qu'utilise chaque instance Cloud Run.
| Variable | Défaut | Ce que cela fait |
|---|---|---|
ISO8583_TCP_PORT | vide | le port. Vide signifie aucun écouteur du tout |
ISO8583_TCP_HOST | 0.0.0.0 | l'interface sur laquelle il se lie |
ISO8583_ALLOWED_CIDRS | vide | adresses et blocs CIDR, séparés par des virgules ou des retours à la ligne, autorisés à se connecter : 203.0.113.0/24, 10.20.0.5, 2001:db8::/32. Vide signifie que tout pair peut se connecter. Un client IPv4 sur une socket double pile (::ffff:203.0.113.7) est comparé aux règles IPv4 comme l'adresse IPv4 qu'il est. Une entrée malformée empêche le processus de démarrer plutôt que d'être ignorée |
ISO8583_TLS_CERT / ISO8583_TLS_KEY | vide | chemins PEM. Les deux ou aucun : l'un sans l'autre empêche la passerelle de démarrer plutôt que de lancer silencieusement un écouteur en clair que quelqu'un croyait chiffré |
ISO8583_MAX_CONNECTIONS | 32 | connexions tenues simultanément ; une de plus est refusée au niveau de la socket plutôt que mise en file |
ISO8583_MAX_MESSAGES_PER_MINUTE | 600 | par connexion, sur un seau à jetons réalimenté en continu. Au-delà, 96 avec le délai de reprise dans DE126 — la connexion n'est pas fermée |
ISO8583_IDLE_TIMEOUT_SECONDS | 180 | silence avant que l'écouteur ne ferme une connexion |
ISO8583_MAX_SIGN_ON_ATTEMPTS | 3 | clés erronées avant la fermeture de la connexion, afin que la socket ne soit pas un oracle à clés |
Chaque message figure dans la trace du monde
Une connexion ayant fait son sign-on écrit dans la trace propre de l'équipe, sous l'acteur
iso8583-wire : un event pour le sign-on, puis un message et un reply par échange, portant
chacun le nom de la connexion (iso8583-0007), le pair, l'équipe, et une **empreinte de la clé
sur huit caractères hexadécimaux** — assez pour distinguer l'identifiant d'un nœud de plateau
d'une clé de banc de test six semaines plus tard, inutilisable comme identifiant en soi. Le rendu
est le même que celui qu'utilise le journal, si bien que **DE052 et DE127 sont supprimés avant
qu'un seul caractère ne soit écrit**. C'est ce qui rend un retrait sur le rail et un retrait REST
distinguables après coup, ce qui est la question que pose un rapprochement.
Le pack de conformité
La liste de ce qu'un switch doit faire correctement, et un exécuteur pour elle :
npm run wire:conformance -- --host=127.0.0.1 --port=8583 --key=<team key> \
--gateway=http://127.0.0.1:8787
npm run wire:conformance -- --host=wire.example --port=8583 --key=… --tls --json
Il compose l'écouteur avec packages/iso8583-wire/test/virtual-switch.ts — le même switch carte
virtuel que pilote la suite de tests, ce qui est précisément le propos : **le pack n'est pas une
description des tests, il est les tests, pointés ailleurs.** Sans --gateway, les cas qui ont
besoin de matériel du Lab (une carte, un accepteur, un terminal, un ordre sans carte) rapportent
SKIP avec le motif et ne sont jamais comptés comme des succès ; la discipline du lien
s'exécute contre n'importe quoi. Le code de sortie est 0 quand rien n'a échoué, 1 dès que
quelque chose a échoué, et --json imprime le rapport entier.
**Un succès dit que l'écouteur parle ce profil. Il ne dit rien de la certification d'un
quelconque réseau carte, et une exécution ne remplace jamais celle-ci.**
| Cas | Messages | Ce qu'un switch doit faire |
|---|---|---|
sign-on<br>faire le sign-on avec la clé d'équipe dans DE127 | 0800 0810 | un 0800 avec DE070 001 et la clé dans DE127 reçoit la réponse 0810 DE039 00, et la réponse ne porte aucun DE127 : un identifiant qui revient est un identifiant présent dans chaque capture du lien. |
sign-on-refused<br>une clé que l'écouteur ne détient pas est refusée, et la socket n'est pas un oracle | 0800 0810 | une clé erronée reçoit la réponse 57 et la connexion est fermée après le nombre de tentatives configuré, de sorte que le lien ne puisse servir à en deviner une. |
unsigned-refused<br>un message financier avant le sign-on est refusé | 0200 0210 | tout message qui n'est pas le sign-on, sur une connexion qui n'a pas fait de sign-on, reçoit la réponse 57 avec DE126 indiquant de faire d'abord le sign-on. Il n'est jamais exécuté. |
credential-once<br>DE127 sur tout message autre que le sign-on est refusé d'emblée | 0800 0100 0200 | un identifiant sur un message financier est refusé avec 57 plutôt qu'ignoré : un terminal qui présente sa clé à chaque message est un terminal dont la clé est dans chaque capture de paquets. |
echo<br>test d'écho | 0800 0810 | un 0800 avec DE070 301 reçoit la réponse 00 tant que le lien est actif. C'est ce avec quoi un switch scrute le lien et le moyen le moins coûteux de distinguer un lien mort d'un lien silencieux. |
authorization<br>un achat chez un accepteur | 0100 0110 | un 0100 portant DE002, DE042 et DE004 reçoit la réponse 0110 avec DE039, et en cas d'approbation avec DE037 et DE038. Le PAN revient MASQUÉ : la réponse est la projection, et la projection le masque.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
authorization-declined<br>un refus est une réponse | 0100 0110 | une autorisation que l'émetteur n'approuvera pas arrive comme un 0110 bien formé avec son propre DE039 - jamais comme une connexion coupée. Une machine qui reçoit le silence n'imprime rien et réessaie.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
reversal<br>l'annulation d'une autorisation, par sa propre référence | 0400 0410 | un 0400 portant le DE037 avec lequel le 0110 est revenu reçoit la réponse 0410 00, et DE090 désigne le message annulé. Un 0400 sans DE037 reçoit la réponse 30.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
withdrawal-cardless<br>un retrait sans carte sur une machine | 0200 0210 | un 0200 avec DE003 010000, SANS DE002 et le code à usage unique dans DE102 reçoit la réponse 0210. L'ordre est consommé exactement une fois : une seconde utilisation du même code est refusée.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
withdrawal-card<br>un retrait avec une carte et son PIN du Lab | 0200 0210 | un 0200 avec DE003 010000, DE002, DE041, DE100 et DE052 reçoit la réponse 0210, et DE052 n'est jamais renvoyé en écho ni jamais journalisé.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
deposit<br>un dépôt sur une machine | 0200 0210 | un 0200 avec DE003 210000, le montant déclaré dans DE004 et DE002 ou DE102 reçoit la réponse 0210 avec l'issue à laquelle le switch est parvenu, reconnaissance comprise.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
balance-inquiry<br>une consultation de solde, qui ne fait rien circuler | 0200 0210 | un 0200 avec DE003 310000, DE100 et DE102 reçoit la réponse 0210 00 avec le montant dans DE126. Elle ne comptabilise rien : DE054 n'est pas dans ce profil et aucune transaction n'est enregistrée.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
clearing<br>une autorisation émise sur le rail est compensée et réglée en net | 0100 0110 | LE PROFIL NE PORTE AUCUN MESSAGE DE COMPENSATION - pas de 0320, pas de 0500, pas de 0600. Ce qui doit tenir, c'est qu'une transaction autorisée sur le rail soit la transaction même que le cycle de compensation de l'acquéreur reprend et règle en net, ce que le Lab démontre par POST /v1/cards/cycles plutôt que par un MTI.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
wire-rest-parity<br>le rail et la voie REST s'accordent, sur l'issue et sur les écritures | 0100 0110 | la même opération envoyée sur le rail et sur la voie carte REST, dans le même monde, atteint le même DE039 et fait circuler le même argent. La réponse EST la projection REST, de sorte qu'une différence ici est une différence dans l'écosystème et non dans le lien.<br><em>nécessite du matériel du Lab (une carte, un accepteur, un terminal) : passez --gateway.</em> |
unknown-mti<br>une famille de messages que le profil ne porte pas est refusée, pas ignorée | 0420 0500 | un MTI hors de 0100/0200/0400/0800 - un avis d'annulation 0420, une réconciliation 0500 - reçoit la réponse 12 avec DE126 nommant les quatre familles. La connexion survit. |
format-error<br>une trame qui n'est pas un message reçoit une réponse, et le lien survit | 0810 | des octets qui ne se décodent pas reçoivent la réponse 30 - sur le MTI de réponse propre à la requête quand le MTI était lisible, sinon sur un 0810 - et la connexion reste active. |
oversized-frame<br>une trame dépassant le maximum du profil met fin à la connexion | 0810 | un en-tête de longueur déclarant plus de 4096 octets, ou zéro, reçoit la réponse 30 une fois et la connexion est fermée : il n'y a dans ce protocole aucun délimiteur sur lequel resynchroniser un flux. |
rate-limit<br>un flot est ralenti, pas déconnecté | 0800 0810 | au-delà du budget par connexion, un message reçoit la réponse 96 avec le délai de reprise dans DE126, et la connexion n'est PAS fermée : un terminal qui n'est que rapide devrait ralentir, pas tomber du réseau.<br><em>un cas limite : passez --include-slow.</em> |
sign-off<br>faire le sign-off, et l'écouteur ferme | 0800 0810 | un 0800 avec DE070 002 reçoit la réponse 00 et la connexion est fermée par l'écouteur, de sorte qu'un switch qui a terminé n'occupe pas d'emplacement. |
_19 cas, dont 10 s'exécutent contre n'importe quel écouteur avec pour tout bagage un hôte, un port et une clé. Généré depuis packages/iso8583-wire/src/conformance.ts par npm run spec:wire._
Il n'y a délibérément **aucun message de compensation dans le pack, parce qu'il n'y en a aucun
dans le profil** (§2 : pas de 0320, pas de 0500, pas de 0600). La compensation et le règlement
sont ici un cycle que l'acquéreur exécute, de sorte que le cas clearing démontre qu'une
transaction autorisée sur le rail est celle que ce cycle reprend et règle en net — via
POST /v1/cards/cycles, et non via un MTI inventé. Pour la même raison, un avis d'annulation
0420 ne figure dans le pack que comme quelque chose qu'un switch doit refuser avec 12 :
l'annulation du profil est 0400/0410.