PR-Comments

This commit is contained in:
Claus-Peter Hübner 2022-03-24 21:35:11 +01:00
parent f2e2f77325
commit 5da36e0448
3 changed files with 61 additions and 50 deletions

View File

@ -292,16 +292,22 @@ Der Prozess *Neue Community erstellen* wird entweder automatisiert beim erstmali
Der oben grafisch dargestellte Ablauf wird in drei grobe Teile untergliedert:
1. )den eigentlichen Community-Prozess "*neue Community erstellen*" (links in grün gehalten), in dem die Community spezifischen Attribute erfasst, geladen und/oder angelegt werden. Dazu gehören neben dem Erfassen der Community eigenen Attributen, das Laden von vordefinierten Standard-Daten wie die Tätigkeitsliste, Berechtigungen, etc. und optional als eigenständiger Prozess die Erfassung bzw das Anlegen von neuen Community-Mitgliedern.
2. das Starten der "*Federation*" als Hintergrundprozess, um die neu erstellte Community im Gradido-Community-Verbund bekannt zu machen. Die technischen Details der *Federation* werden im Dokument [Federation](../TechnicalRequirements/Federation.md " ") beschrieben. Dabei wird
2. das Starten der "*Federation*" als Hintergrundprozess, um die neu erstellte Community im Gradido-Community-Verbund bekannt zu machen. Dietechnischen Details der *Federation* werden im Dokument [Federation](../TechnicalRequirements/Federation.md " ") beschrieben. Dabei wird
* als erstes geprüft, ob in der eigenen Community die notwendigen Attribute wie Community-Key, URL und ggf. weitere korrekt initialisiert und gespeichert sind. Falls nicht wird der Hintergrundprozess mit einem Fehler abgebrochen
* dann werden die Attribute Community-Key und URL in eine *newCommunity*-Message gepackt und asynchron an den Public-Channel der Community-Federation des Gradido-Community-Verbundes gesendet
* Im Anschluss geht der Federation-Prozess in den "Lausch-Modus" auf eingehende Messages am *Public-Channel*. Die Verarbeitung von eingehenden Messages muss so sichergestellt werden, dass einerseits keine Message verloren geht auch bei DownTimes und andererseits, dass eine Message erst aus dem Public-Channel gelöscht wird, sobald diese vollständig abgearbeitet ist. Der Federation-Prozess lauscht auf Messages vom Typ *replyNewCommunity* und *newCommunity*, die bei Empfang entsprechend verarbeitet werden:
* *replyNewCommunity*-Messages werden auf die zuvor gesendete *newCommunity*-Message als Antwort von allen anderen schon im Verbund existierenden Communities erwartet. Je nach MessageState erfolgt eine unterschiedliche Weiterverarbeitung:
* Ist der *MessageState = OK*, dann werden die erhaltenen Daten - Community-Key und URL - von der antwortenden Community in der Community-Datenbank als internen Liste für "*bekannte Communities*" gespeichert. Nach dem Speichern eines neue Community-Eintrags in dieser Liste wird asynchron der dritten und letzten Schritt der Federation *"Community-Communication"* als Hintergrundprozess getriggert und geht dann wieder zurück in den "Lausch-Modus" am Public-Channel.
* Ist der MessageState = requestNewKey, dann erfolgt eine Neugenerierung und Speicherung des eigenen Community-Keys, der dann erneut als *newCommunity*-Message auf den Public-Channel verschickt wird. Danach geht der Federation-Prozess wieder in den "Lauch-Modus", um auf Anworten der existierenden Communities zu warten.
* *newCommunity*-Messages werden von neu erstellten Communities im Rahmen derer Federation in den Public-Channel gesendet. Diese Messages sollten möglichst zeitnah von möglichst vielen schon existierenden Communities beantwortet werden. Dazu wird zuerst in der Community-Datenbank nach Einträgen gesucht, die den gleichen Community-Key aber eine unterschiedliche URL als zu den empfangenen Daten haben:
* Sollte es einen solchen Eintrag geben, dann wird eine *replyNewCommunity*-Message erzeugt mit *MessageState = requestNewKey* und ohne weitere Daten in den Public-Channel zurückgesendet. Danach wird wieder in den "Lausch-Modus" am Public-Channel gewechselt.
* Sollte es keine solche Einträge geben, dann werden die eigenen Daten *Community-Key* und *URL* in eine *replyNewCommunity*-Message gepackt, der *MessageState = OK* gesetzt und direkt in den Public-Channel zurückgesendet. Danach wird wieder in den "Lausch-Modus" am Public-Channel gewechselt.
* Sollte es keine solche Einträge geben, dann werden die eigenen Daten *Community-Ke*y und *URL* in eine *replyNewCommunity*-Message gepackt, der *MessageState = OK* gesetzt und direkt in den Public-Channel zurückgesendet. Danach wird wieder in den "Lausch-Modus" am Public-Channel gewechselt.
* | PR-Kommentar | |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Ulf<br />24.03.2022 | Schitte 1 & 2 sind komplett durch die Federation an sich abgedeckt. Bereits über die Federatierungsschnittstelle wird eine Direktverbindung zum Peer aufgebaut um Daten auszutauschen (die URLs)<br />Mehr infos:<br />[https://en.wikipedia.org/wiki/Kademlia](https://en.wikipedia.org/wiki/Kademlia)[https://github.com/hyperswarm/dht](https://github.com/hyperswarm/dht) |
*
3. und die *"Community-Communication"* als Hintergrundprozess. Dieser liest zuerst die eigenen Community-Daten und geht dann per Direkt-Verbindung über die URL mit der neuen Community in Dialog, um sich zuerst gegenseitig zu authentifizieren und um dann die Community spezifischen Daten untereinander auszutauschen. Der logische Ablauf dieser Kommunikation soll wie folgt dargestellt ablaufen:
![AuthenticateCommunityCommunication](.\image\AuthenticateCommunityCommunication.png " ")
@ -314,7 +320,7 @@ Die aller erste fachliche Kommunikation zwischen einer neu erstellten und einer
1. Community-Infrastruktur ist installiert und aktiv
2. neue Community ist erzeugt und Daten in der Community-DB gespeichert
3. der Hintergrundprozess *Federation* ist am Laufen
3. der Hintergrundprozess *Federatio*n ist am Laufen
* die initiale "newCommunity-Msg" mit den eigenen Community-Daten ist in den Public-Channel versendet
* ein Listener lauscht am Public-Channel auf Antworten (*replyNewCommunity*-Msg) der schon existenten Communities
* ein Listener lauscht am Public-Channel auf initiale "*newCommunity*-Msg" anderer neuer Communities
@ -326,9 +332,7 @@ Die aller erste fachliche Kommunikation zwischen einer neu erstellten und einer
#### Fehlerfälle
### Communities Tradinglevel aushandeln {Communities-Tradinglevel-aushandeln}
### Communities Tradinglevel aushandeln
Im Anwendungsfall *Communities Tradinglevel aushandeln* geht es darum, dass die beiden involvierten Communities sich gegenseitig anfragen und bestätigen auf welchem Level bzw. mit welchen Detailtiefe sie zukünftig Datenaustauschen und miteinander interagieren.
@ -413,7 +417,6 @@ Als Ende diese Anwendungsfalles kann es folgende Konstellationen geben:
#### Fehlerfälle
### Community bearbeiten
*Allgemeine fachliche Beschreibung des Anwendungsfalles.*
@ -438,7 +441,6 @@ Als Ende diese Anwendungsfalles kann es folgende Konstellationen geben:
#### Fehlerfälle
### Trusted Community verbinden
*Allgemeine fachliche Beschreibung des Anwendungsfalles.*
@ -451,7 +453,6 @@ Als Ende diese Anwendungsfalles kann es folgende Konstellationen geben:
#### Fehlerfälle
### Trusted Community lösen
*Allgemeine fachliche Beschreibung des Anwendungsfalles.*
@ -464,7 +465,6 @@ Als Ende diese Anwendungsfalles kann es folgende Konstellationen geben:
#### Fehlerfälle
### Parent Community einrichten
*Allgemeine fachliche Beschreibung des Anwendungsfalles.*
@ -477,7 +477,6 @@ Als Ende diese Anwendungsfalles kann es folgende Konstellationen geben:
#### Fehlerfälle
### Parent Community löschen
*Allgemeine fachliche Beschreibung des Anwendungsfalles.*

View File

@ -28,6 +28,23 @@ A similar solution of authentication to variant A but **without autorization** c
4. *Community-B* will verify the given one-time-code and if valid, decrypt the previous received and encrypted community key from step 1 of the invocation-chain by using the given public key from *community-A*. If the decrypted community-key is equals the own community key, the public key of *community-A* is stored in the entry of *community-A* of the internal community list. As response of the *verifyOneTimeCode* the *community-B* will send back his own public key to *community-A*.
5. *Community-A* will store the received public key of *community-B* in the corresponding entry of the internal community-list.
| PR-Kommentar | zu Punkt 1 in der List oben |
| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ulf<br />24.03.2022 | ComA.org --- (pubKeyA, SaltA, privKeyA(SaltA,pubKeyB) ---> ComB.org<br />
```
<--- (pubKeyB, SaltB, privKeyB(SaltA, SaltB, pubKeyA) ----
```
<br /><br />Das wäre mien Vorschlag, aber ich bin kein Crypto-Experte.<br />Tritt ein Validierungsfehler auf, wird der Call als unauthorized markiert.<br /><br />Vorteil: statless<br />Nachteil: Rechenaufwendig, kann umgangen werden, wenn Salt ein Datum ist und ein solcher Salt eine Gültigkeitsdauer hat - e.g. 10 min. Dann wäre aber SaltB unpraktikabel - für die Validierung auf ComB Seite wäre, dann eine Prüfung des Salt-Datums notwendig um replay Attacken zu verhindern. |
| Claus-Peter<br />24.03.2022 | Da scheint in deinem Bild ein Henne-Ei-Problem zu sein:<br />Wie kommt ComA für seinen ersten Request an ComB zu dem pubKeyB?<br />Den hat ComA zu dem Zeitpunkt doch noch gar nicht, oder?<br />Daher benötigt man einen mehr-schrittigen Handshake zw. den Communities, um diese Keys auszutauschen. |
| **PR-Kommentar** | **zu Punkt 2 in der Liste oben** |
| Ulf<br />24.03.2022 | explain? Out key exchange was done befor, we just need to proof that our current data is correct?! |
| Claus-Peter<br />24.03.2022 | Das ist genau was ich oben schon meinte mit dem Henne-Ei-Problem:<br /><br />Wir sollten dazu noch einmal genau den Ablauf zu den einzelnen Zeitpunkten und welche Daten in welcher Community zu den Zeitpunkten vorliegen bzw über welche Kanäle diese ausgetauscht werden.<br />Ich glaube ich skizziere dies noch einmal möglichst einfach auf... |
The result of this invocation chain is the public key exchange of the involved communities, which is the foundation to authenticate a future cross community communication - see Sequnce 2 and 3.
To reach in Variant B nearly the same security level as in Variant A each community has to integrate several components to process this invocation chain like Variant A does.
@ -42,7 +59,6 @@ The third Variant exchange the all necessary data directly without the step in b
Variant C is quite similar to Variant B, but to exchange all security relevant data in a single request-response-roundtrip bears more security risks and should be avoided.
## Service: "Authenticate Community"
This service must be invoked at first - see Variant B above - to exchange the security relevant data before further cross community communication can be done.
@ -76,8 +92,6 @@ POST https://<New_Community_URL>/authenticateCommunity
*UnknownCommunityException* if the community search with the value of parameter "community-key-A" could not find a matching community entry with this key.
## Service: "Verify OneTimeCode"
This service must be invoked directly after getting the *one-time code*, because this code has a very short expiration time. Together with the public key of *community-A* the one-time code is send as input data to *community-B*. The service verifies the given *one-time code* and if valid it decrypt with the given *public key* the previous receive *community-key-B* from the request *authenticateCommunity*. If this decrypted community-key is equals the own community-key the *public key* is stored in the community-entry of *community-A* of the internal community-list.
@ -111,7 +125,6 @@ POST https://<New_Community_URL>/verifyOneTimeCode
*SecurityException* if the decryption result with the given parameter *public-key* and previous receive *community-key-B* from the request *authenticateCommunity* doesn't match with the own community-key.
## Service: "open Communication"
This service must be used to start a new communication session between two communities to authenticate with the returned JWT-Token further requests.
@ -151,8 +164,6 @@ The requesting *community-A* will initialize these input data:
*SecurityException* if the decrypted community-key-B will not match the own community key.
## Service: "Familiarize communities"
This request is used to exchange data between an existing and a new community. It will be invoked by the existing community, which received a valid *newCommunity*-Message from a new community during the federation process.
@ -253,7 +264,6 @@ A *SecurityException* will be thrown, if the security-accesstoken is not valid o
In case the transferred data can't be stored on service-provider the exception *WriteAccessException* will be thrown.
## Service: "confirm TradingLevel"
With this service a community sends his trading level confirmation to a previous *requestTradingLevel* invocation of another community. The *community-B* invokes this service at *community-A* to confirm the previous received and optionally updated vision of trading level data with *community-A*. This service sends the TradingLevelTO with the confirmed flags for future data exchanges between *community-A* and *community-B*. *Community-A* will store this data in the entry of *community-B* of its internal community list and mark it as a *confirmed admin request* for trading level. The update of a *admin request* to state *confirmed* will inform the administrator of *community-A* to trigger administrative interactions and decisions.
@ -303,7 +313,6 @@ The meaning of the *TradingLevelTO*-attributes in the confirmTradingLevel reques
A *SecurityException* will be thrown, if the security-accesstoken is not valid or the if internal autorization rules like black-listings will not allow access.
## Service: "Member of Community"
Before user A can start any cross-community interactions with user B, this service api can be used to check if user B is a valid member of the other community.

View File

@ -1,105 +1,108 @@
<mxfile host="65bd71144e">
<diagram id="IXdqiLGuknWCw5_Zijm2" name="Seite-1">
<mxGraphModel dx="1088" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2336" pageHeight="1654" math="0" shadow="0">
<mxGraphModel dx="535" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2336" pageHeight="1654" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="21" value="Gradido V1.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" vertex="1" parent="1">
<mxCell id="21" value="Gradido V1.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" parent="1" vertex="1">
<mxGeometry x="40" y="640" width="320" height="40" as="geometry"/>
</mxCell>
<mxCell id="22" value="Redesign RegisterProcess" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="22" value="Redesign RegisterProcess" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="80" y="680" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="23" value="Admin Area" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="23" value="Admin Area" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="80" y="700" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="24" value="Account Overview vs Send Coin" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="24" value="Account Overview vs Send Coin" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="80" y="720" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="25" value="Gradido V2.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" vertex="1" parent="1">
<mxCell id="25" value="Gradido V2.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" parent="1" vertex="1">
<mxGeometry x="400" y="560" width="320" height="40" as="geometry"/>
</mxCell>
<mxCell id="26" value="Community-Readyness 1st-Level (Basics)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="26" value="Community-Readyness 1st-Level (Basics)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="440" y="600" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="27" value="Account-Statistics 1st Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxGeometry x="440" y="620" width="280" height="20" as="geometry"/>
<mxCell id="27" value="Account-Statistics 1st Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="440" y="700" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="28" value="Marketing Multiplication" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="28" value="Marketing Multiplication" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="440" y="640" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="29" value="Gradido V3.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" vertex="1" parent="1">
<mxCell id="29" value="Gradido V3.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" parent="1" vertex="1">
<mxGeometry x="760" y="480" width="320" height="40" as="geometry"/>
</mxCell>
<mxCell id="30" value="Community-Readyness 2nd-Level&amp;nbsp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="30" value="Community-Readyness 2nd-Level&amp;nbsp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="800" y="520" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="31" value="Account-Statistics 2nd Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="31" value="Account-Statistics 2nd Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="800" y="540" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="32" value="Managed Kubernetes" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="32" value="Managed Kubernetes" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="800" y="560" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="33" value="Gradido V4.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" vertex="1" parent="1">
<mxCell id="33" value="Gradido V4.2022" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;gradientColor=#97d077;" parent="1" vertex="1">
<mxGeometry x="1120" y="400" width="320" height="40" as="geometry"/>
</mxCell>
<mxCell id="34" value="Community-Readyness 3rd-Level&amp;nbsp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="34" value="Community-Readyness 3rd-Level&amp;nbsp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="1160" y="440" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="35" value="Marketing Multiplication" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="35" value="Marketing Multiplication" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="1160" y="460" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="36" value="Community Providing Services" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="36" value="Community Providing Services" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="1160" y="480" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="37" value="2022" style="rounded=1;whiteSpace=wrap;html=1;gradientColor=#b3b3b3;fillColor=#f5f5f5;strokeColor=#666666;fontSize=20;fontStyle=1" vertex="1" parent="1">
<mxCell id="37" value="2022" style="rounded=1;whiteSpace=wrap;html=1;gradientColor=#b3b3b3;fillColor=#f5f5f5;strokeColor=#666666;fontSize=20;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="40" y="280" width="1400" height="40" as="geometry"/>
</mxCell>
<mxCell id="38" value="" style="endArrow=none;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" target="37">
<mxCell id="38" value="" style="endArrow=none;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" parent="1" target="37" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="40" y="760" as="sourcePoint"/>
<mxPoint x="580" y="550" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="39" value="" style="endArrow=none;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1">
<mxCell id="39" value="" style="endArrow=none;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="760" as="sourcePoint"/>
<mxPoint x="400.0000000000023" y="320" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="40" value="" style="endArrow=none;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1">
<mxCell id="40" value="" style="endArrow=none;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="760" y="760" as="sourcePoint"/>
<mxPoint x="760.0000000000023" y="320" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="41" value="" style="endArrow=none;html=1;entryX=0.771;entryY=1.063;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" target="37">
<mxCell id="41" value="" style="endArrow=none;html=1;entryX=0.771;entryY=1.063;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" target="37" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1120" y="760" as="sourcePoint"/>
<mxPoint x="1130" y="340" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="42" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.1&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="42" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.1&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" parent="1" vertex="1">
<mxGeometry x="50.000000000002274" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="43" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.2&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="43" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.2&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" parent="1" vertex="1">
<mxGeometry x="410.0000000000023" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="44" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.3&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="44" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.3&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" parent="1" vertex="1">
<mxGeometry x="770.0000000000023" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="45" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.4&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="45" value="&lt;font style=&quot;font-size: 18px&quot;&gt;&lt;b&gt;Q.4&amp;nbsp;&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=#666666;fillColor=#f5f5f5;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#333333;" parent="1" vertex="1">
<mxGeometry x="1130.0000000000023" y="330" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="46" value="Multi Language Support" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="46" value="Multi Language Support" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="440" y="660" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="47" value="One-Database 1st Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxGeometry x="440" y="680" width="280" height="20" as="geometry"/>
<mxCell id="47" value="One-Database 1st Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="440" y="620" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="48" value="One-Database 2nd Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxCell id="48" value="One-Database 2nd Level" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" parent="1" vertex="1">
<mxGeometry x="800" y="580" width="280" height="20" as="geometry"/>
</mxCell>
<mxCell id="49" value="Admin Interface Usertool" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
<mxGeometry x="440" y="680" width="280" height="20" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>