updated docs
@@ -1,102 +0,0 @@
|
||||
digraph SystemOverview {
|
||||
// Graph settings
|
||||
rankdir=TB;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
// Title
|
||||
labelloc="t";
|
||||
label="Soleprint - System Overview";
|
||||
fontsize=16;
|
||||
|
||||
// Styling
|
||||
node [shape=box, style="rounded,filled"];
|
||||
|
||||
// Core Hub
|
||||
subgraph cluster_soleprint {
|
||||
label="Soleprint Hub (port 12000)";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
hub [label="Soleprint\nCore Coordinator", fillcolor="#C8E6C9", shape=box];
|
||||
}
|
||||
|
||||
// Artery System
|
||||
subgraph cluster_artery {
|
||||
label="Artery - Todo lo vital";
|
||||
style=filled;
|
||||
color="#FFEBEE";
|
||||
fillcolor="#FFEBEE";
|
||||
|
||||
veins [label="Veins\n(Stateless Connectors)", fillcolor="#FFCDD2"];
|
||||
shunts [label="Shunts\n(Mock Connectors)", fillcolor="#FFCDD2"];
|
||||
pulses [label="Pulses\n(Composed Flows)", fillcolor="#EF9A9A"];
|
||||
plexus [label="Plexus\n(Full Apps)", fillcolor="#E57373"];
|
||||
}
|
||||
|
||||
// Atlas System
|
||||
subgraph cluster_atlas {
|
||||
label="Atlas - Documentacion accionable";
|
||||
style=filled;
|
||||
color="#E3F2FD";
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
books [label="Books\n(Documentation)", fillcolor="#BBDEFB"];
|
||||
templates [label="Templates\n(Patterns)", fillcolor="#BBDEFB"];
|
||||
depots [label="Depots\n(External Docs)", fillcolor="#90CAF9"];
|
||||
}
|
||||
|
||||
// Station System
|
||||
subgraph cluster_station {
|
||||
label="Station - Centro de control";
|
||||
style=filled;
|
||||
color="#FFF8E1";
|
||||
fillcolor="#FFF8E1";
|
||||
|
||||
tools [label="Tools\n(modelgen, tester, datagen)", fillcolor="#FFECB3"];
|
||||
monitors [label="Monitors\n(databrowse)", fillcolor="#FFECB3"];
|
||||
}
|
||||
|
||||
// External
|
||||
subgraph cluster_external {
|
||||
label="External Services";
|
||||
style=dashed;
|
||||
color=gray;
|
||||
|
||||
jira [label="Jira", fillcolor="#E8EAF6"];
|
||||
slack [label="Slack", fillcolor="#E8EAF6"];
|
||||
google [label="Google", fillcolor="#E8EAF6"];
|
||||
mercadopago [label="MercadoPago", fillcolor="#E8EAF6"];
|
||||
}
|
||||
|
||||
// Managed Room
|
||||
subgraph cluster_room {
|
||||
label="Managed Room (e.g., AMAR)";
|
||||
style=dashed;
|
||||
color="#7B1FA2";
|
||||
|
||||
room_backend [label="Backend\n(Django/FastAPI)", fillcolor="#E1BEE7"];
|
||||
room_frontend [label="Frontend\n(Next.js)", fillcolor="#E1BEE7"];
|
||||
room_db [label="Database\n(PostgreSQL)", fillcolor="#CE93D8", shape=cylinder];
|
||||
}
|
||||
|
||||
// Connections
|
||||
hub -> veins [label="routes"];
|
||||
hub -> books [label="routes"];
|
||||
hub -> tools [label="routes"];
|
||||
|
||||
veins -> jira [label="API"];
|
||||
veins -> slack [label="API"];
|
||||
veins -> google [label="OAuth"];
|
||||
shunts -> mercadopago [label="mock", style=dashed];
|
||||
|
||||
veins -> pulses [label="compose"];
|
||||
pulses -> plexus [label="extend"];
|
||||
|
||||
tools -> room_backend [label="test", style=dashed];
|
||||
monitors -> room_db [label="browse", style=dashed];
|
||||
depots -> room_backend [label="docs", style=dashed];
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: SystemOverview Pages: 1 -->
|
||||
<svg width="968pt" height="448pt"
|
||||
viewBox="0.00 0.00 968.00 448.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 444.38)">
|
||||
<title>SystemOverview</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-444.38 964,-444.38 964,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="480" y="-421.18" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint - System Overview</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_soleprint</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="258,-325.38 258,-404.88 493,-404.88 493,-325.38 258,-325.38"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="375.5" y="-385.68" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint Hub (port 12000)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_artery</title>
|
||||
<polygon fill="#ffebee" stroke="#ffebee" points="8,-8 8,-294.62 304,-294.62 304,-8 8,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="156" y="-275.43" font-family="Helvetica,sans-Serif" font-size="16.00">Artery - Todo lo vital</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_atlas</title>
|
||||
<polygon fill="#e3f2fd" stroke="#e3f2fd" points="312,-215.12 312,-294.62 647,-294.62 647,-215.12 312,-215.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="479.5" y="-275.43" font-family="Helvetica,sans-Serif" font-size="16.00">Atlas - Documentacion accionable</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_station</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="655,-215.12 655,-294.62 951,-294.62 951,-215.12 655,-215.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="803" y="-275.43" font-family="Helvetica,sans-Serif" font-size="16.00">Station - Centro de control</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_external</title>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="312,-98.81 312,-178.31 634,-178.31 634,-98.81 312,-98.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="473" y="-159.11" font-family="Helvetica,sans-Serif" font-size="16.00">External Services</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_room</title>
|
||||
<polygon fill="none" stroke="#7b1fa2" stroke-dasharray="5,2" points="642,-92.75 642,-184.38 952,-184.38 952,-92.75 642,-92.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="797" y="-165.18" font-family="Helvetica,sans-Serif" font-size="16.00">Managed Room</text>
|
||||
</g>
|
||||
<!-- hub -->
|
||||
<g id="node1" class="node">
|
||||
<title>hub</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M417.88,-369.38C417.88,-369.38 332.12,-369.38 332.12,-369.38 326.12,-369.38 320.12,-363.38 320.12,-357.38 320.12,-357.38 320.12,-345.38 320.12,-345.38 320.12,-339.38 326.12,-333.38 332.12,-333.38 332.12,-333.38 417.88,-333.38 417.88,-333.38 423.88,-333.38 429.88,-339.38 429.88,-345.38 429.88,-345.38 429.88,-357.38 429.88,-357.38 429.88,-363.38 423.88,-369.38 417.88,-369.38"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="375" y="-354.43" font-family="Helvetica,sans-Serif" font-size="11.00">Soleprint</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="375" y="-340.93" font-family="Helvetica,sans-Serif" font-size="11.00">Core Coordinator</text>
|
||||
</g>
|
||||
<!-- veins -->
|
||||
<g id="node2" class="node">
|
||||
<title>veins</title>
|
||||
<path fill="#ffcdd2" stroke="black" d="M146,-259.12C146,-259.12 28,-259.12 28,-259.12 22,-259.12 16,-253.12 16,-247.12 16,-247.12 16,-235.12 16,-235.12 16,-229.12 22,-223.12 28,-223.12 28,-223.12 146,-223.12 146,-223.12 152,-223.12 158,-229.12 158,-235.12 158,-235.12 158,-247.12 158,-247.12 158,-253.12 152,-259.12 146,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="87" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Veins</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="87" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(Stateless Connectors)</text>
|
||||
</g>
|
||||
<!-- hub->veins -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>hub->veins</title>
|
||||
<path fill="none" stroke="black" d="M319.94,-340.62C277.04,-331.84 216.64,-316.87 167,-294.62 150.13,-287.06 132.8,-276.15 118.61,-266.23"/>
|
||||
<polygon fill="black" stroke="black" points="120.72,-263.44 110.56,-260.46 116.64,-269.13 120.72,-263.44"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="231.88" y="-305.88" font-family="Helvetica,sans-Serif" font-size="10.00">routes</text>
|
||||
</g>
|
||||
<!-- books -->
|
||||
<g id="node6" class="node">
|
||||
<title>books</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M417.5,-259.12C417.5,-259.12 332.5,-259.12 332.5,-259.12 326.5,-259.12 320.5,-253.12 320.5,-247.12 320.5,-247.12 320.5,-235.12 320.5,-235.12 320.5,-229.12 326.5,-223.12 332.5,-223.12 332.5,-223.12 417.5,-223.12 417.5,-223.12 423.5,-223.12 429.5,-229.12 429.5,-235.12 429.5,-235.12 429.5,-247.12 429.5,-247.12 429.5,-253.12 423.5,-259.12 417.5,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="375" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Books</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="375" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(Documentation)</text>
|
||||
</g>
|
||||
<!-- hub->books -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>hub->books</title>
|
||||
<path fill="none" stroke="black" d="M375,-332.98C375,-316.25 375,-290.66 375,-270.9"/>
|
||||
<polygon fill="black" stroke="black" points="378.5,-270.99 375,-260.99 371.5,-270.99 378.5,-270.99"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="390.38" y="-305.88" font-family="Helvetica,sans-Serif" font-size="10.00">routes</text>
|
||||
</g>
|
||||
<!-- tools -->
|
||||
<g id="node9" class="node">
|
||||
<title>tools</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M823,-259.12C823,-259.12 675,-259.12 675,-259.12 669,-259.12 663,-253.12 663,-247.12 663,-247.12 663,-235.12 663,-235.12 663,-229.12 669,-223.12 675,-223.12 675,-223.12 823,-223.12 823,-223.12 829,-223.12 835,-229.12 835,-235.12 835,-235.12 835,-247.12 835,-247.12 835,-253.12 829,-259.12 823,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="749" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Tools</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="749" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(modelgen, tester, datagen)</text>
|
||||
</g>
|
||||
<!-- hub->tools -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>hub->tools</title>
|
||||
<path fill="none" stroke="black" d="M430.22,-344.05C486.88,-336.46 576.95,-321.28 651,-294.62 672.05,-287.05 694.12,-275.57 711.98,-265.28"/>
|
||||
<polygon fill="black" stroke="black" points="713.56,-268.41 720.4,-260.32 710.01,-262.38 713.56,-268.41"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="637.44" y="-305.88" font-family="Helvetica,sans-Serif" font-size="10.00">routes</text>
|
||||
</g>
|
||||
<!-- pulses -->
|
||||
<g id="node4" class="node">
|
||||
<title>pulses</title>
|
||||
<path fill="#ef9a9a" stroke="black" d="M133.62,-142.81C133.62,-142.81 40.38,-142.81 40.38,-142.81 34.38,-142.81 28.38,-136.81 28.38,-130.81 28.38,-130.81 28.38,-118.81 28.38,-118.81 28.38,-112.81 34.38,-106.81 40.38,-106.81 40.38,-106.81 133.62,-106.81 133.62,-106.81 139.62,-106.81 145.62,-112.81 145.62,-118.81 145.62,-118.81 145.62,-130.81 145.62,-130.81 145.62,-136.81 139.62,-142.81 133.62,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="87" y="-127.86" font-family="Helvetica,sans-Serif" font-size="11.00">Pulses</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="87" y="-114.36" font-family="Helvetica,sans-Serif" font-size="11.00">(Composed Flows)</text>
|
||||
</g>
|
||||
<!-- veins->pulses -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>veins->pulses</title>
|
||||
<path fill="none" stroke="black" d="M87,-222.76C87,-204.61 87,-175.84 87,-154.34"/>
|
||||
<polygon fill="black" stroke="black" points="90.5,-154.48 87,-144.48 83.5,-154.48 90.5,-154.48"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="109.12" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">compose</text>
|
||||
</g>
|
||||
<!-- jira -->
|
||||
<g id="node11" class="node">
|
||||
<title>jira</title>
|
||||
<path fill="#e8eaf6" stroke="black" d="M362,-142.81C362,-142.81 332,-142.81 332,-142.81 326,-142.81 320,-136.81 320,-130.81 320,-130.81 320,-118.81 320,-118.81 320,-112.81 326,-106.81 332,-106.81 332,-106.81 362,-106.81 362,-106.81 368,-106.81 374,-112.81 374,-118.81 374,-118.81 374,-130.81 374,-130.81 374,-136.81 368,-142.81 362,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="347" y="-121.11" font-family="Helvetica,sans-Serif" font-size="11.00">Jira</text>
|
||||
</g>
|
||||
<!-- veins->jira -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>veins->jira</title>
|
||||
<path fill="none" stroke="black" d="M140.6,-222.66C149.39,-220.01 158.42,-217.4 167,-215.12 229,-198.71 255.03,-220.54 308,-184.38 319.35,-176.62 328.26,-164.37 334.68,-153.07"/>
|
||||
<polygon fill="black" stroke="black" points="337.65,-154.94 339.18,-144.46 331.45,-151.7 337.65,-154.94"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="300.73" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">API</text>
|
||||
</g>
|
||||
<!-- slack -->
|
||||
<g id="node12" class="node">
|
||||
<title>slack</title>
|
||||
<path fill="#e8eaf6" stroke="black" d="M434,-142.81C434,-142.81 404,-142.81 404,-142.81 398,-142.81 392,-136.81 392,-130.81 392,-130.81 392,-118.81 392,-118.81 392,-112.81 398,-106.81 404,-106.81 404,-106.81 434,-106.81 434,-106.81 440,-106.81 446,-112.81 446,-118.81 446,-118.81 446,-130.81 446,-130.81 446,-136.81 440,-142.81 434,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="419" y="-121.11" font-family="Helvetica,sans-Serif" font-size="11.00">Slack</text>
|
||||
</g>
|
||||
<!-- veins->slack -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>veins->slack</title>
|
||||
<path fill="none" stroke="black" d="M136.47,-222.69C146.47,-219.73 156.99,-217.01 167,-215.12 230.92,-203.12 248.99,-216.66 313,-205.12 344.93,-199.37 357.24,-204.11 383,-184.38 393.48,-176.34 401.63,-164.31 407.5,-153.25"/>
|
||||
<polygon fill="black" stroke="black" points="410.55,-154.97 411.77,-144.45 404.25,-151.91 410.55,-154.97"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="378.08" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">API</text>
|
||||
</g>
|
||||
<!-- google -->
|
||||
<g id="node13" class="node">
|
||||
<title>google</title>
|
||||
<path fill="#e8eaf6" stroke="black" d="M506.12,-142.81C506.12,-142.81 475.88,-142.81 475.88,-142.81 469.88,-142.81 463.88,-136.81 463.88,-130.81 463.88,-130.81 463.88,-118.81 463.88,-118.81 463.88,-112.81 469.88,-106.81 475.88,-106.81 475.88,-106.81 506.12,-106.81 506.12,-106.81 512.12,-106.81 518.12,-112.81 518.12,-118.81 518.12,-118.81 518.12,-130.81 518.12,-130.81 518.12,-136.81 512.12,-142.81 506.12,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="491" y="-121.11" font-family="Helvetica,sans-Serif" font-size="11.00">Google</text>
|
||||
</g>
|
||||
<!-- veins->google -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>veins->google</title>
|
||||
<path fill="none" stroke="black" d="M136.01,-222.63C146.14,-219.63 156.82,-216.91 167,-215.12 264.72,-197.96 292.34,-222.58 390,-205.12 419.85,-199.79 431.12,-203.07 455,-184.38 465.33,-176.29 473.42,-164.36 479.3,-153.37"/>
|
||||
<polygon fill="black" stroke="black" points="482.32,-155.15 483.58,-144.64 476.03,-152.07 482.32,-155.15"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="458.15" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">OAuth</text>
|
||||
</g>
|
||||
<!-- shunts -->
|
||||
<g id="node3" class="node">
|
||||
<title>shunts</title>
|
||||
<path fill="#ffcdd2" stroke="black" d="M283.75,-259.12C283.75,-259.12 188.25,-259.12 188.25,-259.12 182.25,-259.12 176.25,-253.12 176.25,-247.12 176.25,-247.12 176.25,-235.12 176.25,-235.12 176.25,-229.12 182.25,-223.12 188.25,-223.12 188.25,-223.12 283.75,-223.12 283.75,-223.12 289.75,-223.12 295.75,-229.12 295.75,-235.12 295.75,-235.12 295.75,-247.12 295.75,-247.12 295.75,-253.12 289.75,-259.12 283.75,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="236" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Shunts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="236" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(Mock Connectors)</text>
|
||||
</g>
|
||||
<!-- mercadopago -->
|
||||
<g id="node14" class="node">
|
||||
<title>mercadopago</title>
|
||||
<path fill="#e8eaf6" stroke="black" d="M613.75,-142.81C613.75,-142.81 548.25,-142.81 548.25,-142.81 542.25,-142.81 536.25,-136.81 536.25,-130.81 536.25,-130.81 536.25,-118.81 536.25,-118.81 536.25,-112.81 542.25,-106.81 548.25,-106.81 548.25,-106.81 613.75,-106.81 613.75,-106.81 619.75,-106.81 625.75,-112.81 625.75,-118.81 625.75,-118.81 625.75,-130.81 625.75,-130.81 625.75,-136.81 619.75,-142.81 613.75,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="581" y="-121.11" font-family="Helvetica,sans-Serif" font-size="11.00">MercadoPago</text>
|
||||
</g>
|
||||
<!-- shunts->mercadopago -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>shunts->mercadopago</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M280.02,-222.71C289.15,-219.71 298.79,-216.97 308,-215.12 404.38,-195.85 445.68,-239.58 527,-184.38 539.87,-175.64 551.86,-163.27 561.25,-152.15"/>
|
||||
<polygon fill="black" stroke="black" points="563.97,-154.36 567.54,-144.39 558.53,-149.95 563.97,-154.36"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="526.27" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">mock</text>
|
||||
</g>
|
||||
<!-- plexus -->
|
||||
<g id="node5" class="node">
|
||||
<title>plexus</title>
|
||||
<path fill="#e57373" stroke="black" d="M112.25,-52C112.25,-52 61.75,-52 61.75,-52 55.75,-52 49.75,-46 49.75,-40 49.75,-40 49.75,-28 49.75,-28 49.75,-22 55.75,-16 61.75,-16 61.75,-16 112.25,-16 112.25,-16 118.25,-16 124.25,-22 124.25,-28 124.25,-28 124.25,-40 124.25,-40 124.25,-46 118.25,-52 112.25,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="87" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00">Plexus</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="87" y="-23.55" font-family="Helvetica,sans-Serif" font-size="11.00">(Full Apps)</text>
|
||||
</g>
|
||||
<!-- pulses->plexus -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>pulses->plexus</title>
|
||||
<path fill="none" stroke="black" d="M87,-106.69C87,-94.48 87,-77.78 87,-63.57"/>
|
||||
<polygon fill="black" stroke="black" points="90.5,-63.89 87,-53.89 83.5,-63.89 90.5,-63.89"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="103.88" y="-73.25" font-family="Helvetica,sans-Serif" font-size="10.00">extend</text>
|
||||
</g>
|
||||
<!-- templates -->
|
||||
<g id="node7" class="node">
|
||||
<title>templates</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M506.75,-259.12C506.75,-259.12 459.25,-259.12 459.25,-259.12 453.25,-259.12 447.25,-253.12 447.25,-247.12 447.25,-247.12 447.25,-235.12 447.25,-235.12 447.25,-229.12 453.25,-223.12 459.25,-223.12 459.25,-223.12 506.75,-223.12 506.75,-223.12 512.75,-223.12 518.75,-229.12 518.75,-235.12 518.75,-235.12 518.75,-247.12 518.75,-247.12 518.75,-253.12 512.75,-259.12 506.75,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="483" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Templates</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="483" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(Patterns)</text>
|
||||
</g>
|
||||
<!-- depots -->
|
||||
<g id="node8" class="node">
|
||||
<title>depots</title>
|
||||
<path fill="#90caf9" stroke="black" d="M626.75,-259.12C626.75,-259.12 549.25,-259.12 549.25,-259.12 543.25,-259.12 537.25,-253.12 537.25,-247.12 537.25,-247.12 537.25,-235.12 537.25,-235.12 537.25,-229.12 543.25,-223.12 549.25,-223.12 549.25,-223.12 626.75,-223.12 626.75,-223.12 632.75,-223.12 638.75,-229.12 638.75,-235.12 638.75,-235.12 638.75,-247.12 638.75,-247.12 638.75,-253.12 632.75,-259.12 626.75,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Depots</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="588" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(External Docs)</text>
|
||||
</g>
|
||||
<!-- room_backend -->
|
||||
<g id="node15" class="node">
|
||||
<title>room_backend</title>
|
||||
<path fill="#e1bee7" stroke="black" d="M744.38,-142.81C744.38,-142.81 661.62,-142.81 661.62,-142.81 655.62,-142.81 649.62,-136.81 649.62,-130.81 649.62,-130.81 649.62,-118.81 649.62,-118.81 649.62,-112.81 655.62,-106.81 661.62,-106.81 661.62,-106.81 744.38,-106.81 744.38,-106.81 750.38,-106.81 756.38,-112.81 756.38,-118.81 756.38,-118.81 756.38,-130.81 756.38,-130.81 756.38,-136.81 750.38,-142.81 744.38,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="703" y="-127.86" font-family="Helvetica,sans-Serif" font-size="11.00">Backend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="703" y="-114.36" font-family="Helvetica,sans-Serif" font-size="11.00">(Django/FastAPI)</text>
|
||||
</g>
|
||||
<!-- depots->room_backend -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>depots->room_backend</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M605.47,-222.76C624.74,-203.6 655.94,-172.59 677.85,-150.81"/>
|
||||
<polygon fill="black" stroke="black" points="680.05,-153.56 684.67,-144.03 675.11,-148.6 680.05,-153.56"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="646.45" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">docs</text>
|
||||
</g>
|
||||
<!-- tools->room_backend -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>tools->room_backend</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M742.01,-222.76C734.61,-204.36 722.81,-175.03 714.12,-153.45"/>
|
||||
<polygon fill="black" stroke="black" points="717.45,-152.34 710.47,-144.37 710.95,-154.95 717.45,-152.34"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="743.5" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">test</text>
|
||||
</g>
|
||||
<!-- monitors -->
|
||||
<g id="node10" class="node">
|
||||
<title>monitors</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M930.75,-259.12C930.75,-259.12 865.25,-259.12 865.25,-259.12 859.25,-259.12 853.25,-253.12 853.25,-247.12 853.25,-247.12 853.25,-235.12 853.25,-235.12 853.25,-229.12 859.25,-223.12 865.25,-223.12 865.25,-223.12 930.75,-223.12 930.75,-223.12 936.75,-223.12 942.75,-229.12 942.75,-235.12 942.75,-235.12 942.75,-247.12 942.75,-247.12 942.75,-253.12 936.75,-259.12 930.75,-259.12"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="898" y="-244.18" font-family="Helvetica,sans-Serif" font-size="11.00">Monitors</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="898" y="-230.68" font-family="Helvetica,sans-Serif" font-size="11.00">(databrowse)</text>
|
||||
</g>
|
||||
<!-- room_db -->
|
||||
<g id="node17" class="node">
|
||||
<title>room_db</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M944,-144.5C944,-146.91 924.28,-148.88 900,-148.88 875.72,-148.88 856,-146.91 856,-144.5 856,-144.5 856,-105.12 856,-105.12 856,-102.71 875.72,-100.75 900,-100.75 924.28,-100.75 944,-102.71 944,-105.12 944,-105.12 944,-144.5 944,-144.5"/>
|
||||
<path fill="none" stroke="black" d="M944,-144.5C944,-142.09 924.28,-140.12 900,-140.12 875.72,-140.12 856,-142.09 856,-144.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="900" y="-127.86" font-family="Helvetica,sans-Serif" font-size="11.00">Database</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="900" y="-114.36" font-family="Helvetica,sans-Serif" font-size="11.00">(PostgreSQL)</text>
|
||||
</g>
|
||||
<!-- monitors->room_db -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>monitors->room_db</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M898.3,-222.76C898.59,-206.37 899.03,-181.3 899.39,-160.77"/>
|
||||
<polygon fill="black" stroke="black" points="902.89,-160.87 899.56,-150.81 895.89,-160.75 902.89,-160.87"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="916.45" y="-195.62" font-family="Helvetica,sans-Serif" font-size="10.00">browse</text>
|
||||
</g>
|
||||
<!-- room_frontend -->
|
||||
<g id="node16" class="node">
|
||||
<title>room_frontend</title>
|
||||
<path fill="#e1bee7" stroke="black" d="M826,-142.81C826,-142.81 786,-142.81 786,-142.81 780,-142.81 774,-136.81 774,-130.81 774,-130.81 774,-118.81 774,-118.81 774,-112.81 780,-106.81 786,-106.81 786,-106.81 826,-106.81 826,-106.81 832,-106.81 838,-112.81 838,-118.81 838,-118.81 838,-130.81 838,-130.81 838,-136.81 832,-142.81 826,-142.81"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="806" y="-127.86" font-family="Helvetica,sans-Serif" font-size="11.00">Frontend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="806" y="-114.36" font-family="Helvetica,sans-Serif" font-size="11.00">(Next.js)</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,86 +0,0 @@
|
||||
digraph ArteryHierarchy {
|
||||
// Graph settings
|
||||
rankdir=LR;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
// Title
|
||||
labelloc="t";
|
||||
label="Artery - Connector Hierarchy";
|
||||
fontsize=16;
|
||||
|
||||
// Styling
|
||||
node [shape=box, style="rounded,filled"];
|
||||
|
||||
// Main hierarchy
|
||||
subgraph cluster_main {
|
||||
label="Evolution Path";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
vein [label="Vein\n\nStateless API connector\ne.g., Jira, Slack, Google", fillcolor="#C8E6C9", width=2.5];
|
||||
pulse [label="Pulse\n\nVein + Room + Depot\ne.g., Jira for AMAR project", fillcolor="#A5D6A7", width=2.5];
|
||||
plexus [label="Plexus\n\nFull app: backend + frontend + DB\ne.g., WhatsApp with chat UI", fillcolor="#81C784", width=2.5];
|
||||
}
|
||||
|
||||
// Mock path
|
||||
subgraph cluster_mock {
|
||||
label="Testing Path";
|
||||
style=filled;
|
||||
color="#FFF3E0";
|
||||
fillcolor="#FFF3E0";
|
||||
|
||||
shunt [label="Shunt\n\nFake connector for testing\ne.g., mercadopago mock", fillcolor="#FFCC80", width=2.5];
|
||||
}
|
||||
|
||||
// Connections
|
||||
vein -> pulse [label="+ Room\n+ Depot"];
|
||||
pulse -> plexus [label="+ Backend\n+ Frontend\n+ DB"];
|
||||
vein -> shunt [label="mock", style=dashed, constraint=false];
|
||||
|
||||
// Properties table
|
||||
subgraph cluster_props {
|
||||
label="Properties";
|
||||
style=filled;
|
||||
color="#F5F5F5";
|
||||
fillcolor="#F5F5F5";
|
||||
|
||||
props [shape=plaintext, label=<
|
||||
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="8">
|
||||
<TR>
|
||||
<TD BGCOLOR="#EEEEEE"><B>Type</B></TD>
|
||||
<TD BGCOLOR="#EEEEEE"><B>State</B></TD>
|
||||
<TD BGCOLOR="#EEEEEE"><B>Frontend</B></TD>
|
||||
<TD BGCOLOR="#EEEEEE"><B>Deploy</B></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>Vein</TD>
|
||||
<TD>None (or OAuth)</TD>
|
||||
<TD>Optional test UI</TD>
|
||||
<TD>With soleprint</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>Shunt</TD>
|
||||
<TD>Configurable</TD>
|
||||
<TD>Config UI</TD>
|
||||
<TD>With soleprint</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>Pulse</TD>
|
||||
<TD>Vein + config</TD>
|
||||
<TD>Uses vein's</TD>
|
||||
<TD>With soleprint</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD>Plexus</TD>
|
||||
<TD>Full app state</TD>
|
||||
<TD>Required</TD>
|
||||
<TD>Self-contained</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
>];
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: ArteryHierarchy Pages: 1 -->
|
||||
<svg width="972pt" height="487pt"
|
||||
viewBox="0.00 0.00 972.00 487.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 482.5)">
|
||||
<title>ArteryHierarchy</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-482.5 968,-482.5 968,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="482" y="-459.3" font-family="Helvetica,sans-Serif" font-size="16.00">Artery - Connector Hierarchy</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_main</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="107.12,-8 107.12,-113 956,-113 956,-8 107.12,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="531.56" y="-93.8" font-family="Helvetica,sans-Serif" font-size="16.00">Evolution Path</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_mock</title>
|
||||
<polygon fill="#fff3e0" stroke="#fff3e0" points="107.12,-121 107.12,-226 303.12,-226 303.12,-121 107.12,-121"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-206.8" font-family="Helvetica,sans-Serif" font-size="16.00">Testing Path</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_props</title>
|
||||
<polygon fill="#f5f5f5" stroke="#f5f5f5" points="8,-234 8,-443 402.25,-443 402.25,-234 8,-234"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-423.8" font-family="Helvetica,sans-Serif" font-size="16.00">Properties</text>
|
||||
</g>
|
||||
<!-- vein -->
|
||||
<g id="node1" class="node">
|
||||
<title>vein</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M283.12,-77.75C283.12,-77.75 127.12,-77.75 127.12,-77.75 121.12,-77.75 115.12,-71.75 115.12,-65.75 115.12,-65.75 115.12,-28.25 115.12,-28.25 115.12,-22.25 121.12,-16.25 127.12,-16.25 127.12,-16.25 283.12,-16.25 283.12,-16.25 289.12,-16.25 295.12,-22.25 295.12,-28.25 295.12,-28.25 295.12,-65.75 295.12,-65.75 295.12,-71.75 289.12,-77.75 283.12,-77.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">Vein</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-36.8" font-family="Helvetica,sans-Serif" font-size="11.00">Stateless API connector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-23.3" font-family="Helvetica,sans-Serif" font-size="11.00">e.g., Jira, Slack, Google</text>
|
||||
</g>
|
||||
<!-- pulse -->
|
||||
<g id="node2" class="node">
|
||||
<title>pulse</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M638.75,-77.75C638.75,-77.75 482.75,-77.75 482.75,-77.75 476.75,-77.75 470.75,-71.75 470.75,-65.75 470.75,-65.75 470.75,-28.25 470.75,-28.25 470.75,-22.25 476.75,-16.25 482.75,-16.25 482.75,-16.25 638.75,-16.25 638.75,-16.25 644.75,-16.25 650.75,-22.25 650.75,-28.25 650.75,-28.25 650.75,-65.75 650.75,-65.75 650.75,-71.75 644.75,-77.75 638.75,-77.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="560.75" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">Pulse</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="560.75" y="-36.8" font-family="Helvetica,sans-Serif" font-size="11.00">Vein + Room + Depot</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="560.75" y="-23.3" font-family="Helvetica,sans-Serif" font-size="11.00">e.g., Jira for AMAR project</text>
|
||||
</g>
|
||||
<!-- vein->pulse -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>vein->pulse</title>
|
||||
<path fill="none" stroke="black" d="M295.36,-47C345.2,-47 407.45,-47 459.03,-47"/>
|
||||
<polygon fill="black" stroke="black" points="459.03,-50.5 469.03,-47 459.03,-43.5 459.03,-50.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="432.5" y="-63" font-family="Helvetica,sans-Serif" font-size="10.00">+ Room</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="432.5" y="-50.25" font-family="Helvetica,sans-Serif" font-size="10.00">+ Depot</text>
|
||||
</g>
|
||||
<!-- shunt -->
|
||||
<g id="node4" class="node">
|
||||
<title>shunt</title>
|
||||
<path fill="#ffcc80" stroke="black" d="M283.12,-190.75C283.12,-190.75 127.12,-190.75 127.12,-190.75 121.12,-190.75 115.12,-184.75 115.12,-178.75 115.12,-178.75 115.12,-141.25 115.12,-141.25 115.12,-135.25 121.12,-129.25 127.12,-129.25 127.12,-129.25 283.12,-129.25 283.12,-129.25 289.12,-129.25 295.12,-135.25 295.12,-141.25 295.12,-141.25 295.12,-178.75 295.12,-178.75 295.12,-184.75 289.12,-190.75 283.12,-190.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-176.3" font-family="Helvetica,sans-Serif" font-size="11.00">Shunt</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-149.8" font-family="Helvetica,sans-Serif" font-size="11.00">Fake connector for testing</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="205.12" y="-136.3" font-family="Helvetica,sans-Serif" font-size="11.00">e.g., mercadopago mock</text>
|
||||
</g>
|
||||
<!-- vein->shunt -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>vein->shunt</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M205.12,-78.18C205.12,-90.4 205.12,-104.63 205.12,-117.75"/>
|
||||
<polygon fill="black" stroke="black" points="201.63,-117.41 205.13,-127.41 208.63,-117.41 201.63,-117.41"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="195.75" y="-100.38" font-family="Helvetica,sans-Serif" font-size="10.00">mock</text>
|
||||
</g>
|
||||
<!-- plexus -->
|
||||
<g id="node3" class="node">
|
||||
<title>plexus</title>
|
||||
<path fill="#81c784" stroke="black" d="M936,-77.75C936,-77.75 752.75,-77.75 752.75,-77.75 746.75,-77.75 740.75,-71.75 740.75,-65.75 740.75,-65.75 740.75,-28.25 740.75,-28.25 740.75,-22.25 746.75,-16.25 752.75,-16.25 752.75,-16.25 936,-16.25 936,-16.25 942,-16.25 948,-22.25 948,-28.25 948,-28.25 948,-65.75 948,-65.75 948,-71.75 942,-77.75 936,-77.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="844.38" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">Plexus</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="844.38" y="-36.8" font-family="Helvetica,sans-Serif" font-size="11.00">Full app: backend + frontend + DB</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="844.38" y="-23.3" font-family="Helvetica,sans-Serif" font-size="11.00">e.g., WhatsApp with chat UI</text>
|
||||
</g>
|
||||
<!-- pulse->plexus -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>pulse->plexus</title>
|
||||
<path fill="none" stroke="black" d="M651.24,-47C675.94,-47 703.07,-47 728.97,-47"/>
|
||||
<polygon fill="black" stroke="black" points="728.86,-50.5 738.86,-47 728.86,-43.5 728.86,-50.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="695.75" y="-75.75" font-family="Helvetica,sans-Serif" font-size="10.00">+ Backend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="695.75" y="-63" font-family="Helvetica,sans-Serif" font-size="10.00">+ Frontend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="695.75" y="-50.25" font-family="Helvetica,sans-Serif" font-size="10.00">+ DB</text>
|
||||
</g>
|
||||
<!-- props -->
|
||||
<g id="node5" class="node">
|
||||
<title>props</title>
|
||||
<path fill="lightgrey" stroke="none" d="M382.25,-407.75C382.25,-407.75 28,-407.75 28,-407.75 22,-407.75 16,-401.75 16,-395.75 16,-395.75 16,-254.25 16,-254.25 16,-248.25 22,-242.25 28,-242.25 28,-242.25 382.25,-242.25 382.25,-242.25 388.25,-242.25 394.25,-248.25 394.25,-254.25 394.25,-254.25 394.25,-395.75 394.25,-395.75 394.25,-401.75 388.25,-407.75 382.25,-407.75"/>
|
||||
<polygon fill="#eeeeee" stroke="none" points="24,-372.25 24,-403.75 78,-403.75 78,-372.25 24,-372.25"/>
|
||||
<polygon fill="none" stroke="black" points="24,-372.25 24,-403.75 78,-403.75 78,-372.25 24,-372.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="36.75" y="-385.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="11.00">Type</text>
|
||||
<polygon fill="#eeeeee" stroke="none" points="78,-372.25 78,-403.75 186,-403.75 186,-372.25 78,-372.25"/>
|
||||
<polygon fill="none" stroke="black" points="78,-372.25 78,-403.75 186,-403.75 186,-372.25 78,-372.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="115.12" y="-385.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="11.00">State</text>
|
||||
<polygon fill="#eeeeee" stroke="none" points="186,-372.25 186,-403.75 291,-403.75 291,-372.25 186,-372.25"/>
|
||||
<polygon fill="none" stroke="black" points="186,-372.25 186,-403.75 291,-403.75 291,-372.25 186,-372.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="211.12" y="-385.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="11.00">Frontend</text>
|
||||
<polygon fill="#eeeeee" stroke="none" points="291,-372.25 291,-403.75 386.25,-403.75 386.25,-372.25 291,-372.25"/>
|
||||
<polygon fill="none" stroke="black" points="291,-372.25 291,-403.75 386.25,-403.75 386.25,-372.25 291,-372.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="317.25" y="-385.3" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="11.00">Deploy</text>
|
||||
<polygon fill="none" stroke="black" points="24,-340.75 24,-372.25 78,-372.25 78,-340.75 24,-340.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="39.38" y="-352.8" font-family="Helvetica,sans-Serif" font-size="11.00">Vein</text>
|
||||
<polygon fill="none" stroke="black" points="78,-340.75 78,-372.25 186,-372.25 186,-340.75 78,-340.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="87" y="-352.8" font-family="Helvetica,sans-Serif" font-size="11.00">None (or OAuth)</text>
|
||||
<polygon fill="none" stroke="black" points="186,-340.75 186,-372.25 291,-372.25 291,-340.75 186,-340.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="195" y="-352.8" font-family="Helvetica,sans-Serif" font-size="11.00">Optional test UI</text>
|
||||
<polygon fill="none" stroke="black" points="291,-340.75 291,-372.25 386.25,-372.25 386.25,-340.75 291,-340.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="300.38" y="-352.8" font-family="Helvetica,sans-Serif" font-size="11.00">With soleprint</text>
|
||||
<polygon fill="none" stroke="black" points="24,-309.25 24,-340.75 78,-340.75 78,-309.25 24,-309.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="35.25" y="-321.3" font-family="Helvetica,sans-Serif" font-size="11.00">Shunt</text>
|
||||
<polygon fill="none" stroke="black" points="78,-309.25 78,-340.75 186,-340.75 186,-309.25 78,-309.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="97.5" y="-321.3" font-family="Helvetica,sans-Serif" font-size="11.00">Configurable</text>
|
||||
<polygon fill="none" stroke="black" points="186,-309.25 186,-340.75 291,-340.75 291,-309.25 186,-309.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="213.75" y="-321.3" font-family="Helvetica,sans-Serif" font-size="11.00">Config UI</text>
|
||||
<polygon fill="none" stroke="black" points="291,-309.25 291,-340.75 386.25,-340.75 386.25,-309.25 291,-309.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="300.38" y="-321.3" font-family="Helvetica,sans-Serif" font-size="11.00">With soleprint</text>
|
||||
<polygon fill="none" stroke="black" points="24,-277.75 24,-309.25 78,-309.25 78,-277.75 24,-277.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="36.38" y="-289.8" font-family="Helvetica,sans-Serif" font-size="11.00">Pulse</text>
|
||||
<polygon fill="none" stroke="black" points="78,-277.75 78,-309.25 186,-309.25 186,-277.75 78,-277.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="95.62" y="-289.8" font-family="Helvetica,sans-Serif" font-size="11.00">Vein + config</text>
|
||||
<polygon fill="none" stroke="black" points="186,-277.75 186,-309.25 291,-309.25 291,-277.75 186,-277.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="207" y="-289.8" font-family="Helvetica,sans-Serif" font-size="11.00">Uses vein's</text>
|
||||
<polygon fill="none" stroke="black" points="291,-277.75 291,-309.25 386.25,-309.25 386.25,-277.75 291,-277.75"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="300.38" y="-289.8" font-family="Helvetica,sans-Serif" font-size="11.00">With soleprint</text>
|
||||
<polygon fill="none" stroke="black" points="24,-246.25 24,-277.75 78,-277.75 78,-246.25 24,-246.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="33" y="-258.3" font-family="Helvetica,sans-Serif" font-size="11.00">Plexus</text>
|
||||
<polygon fill="none" stroke="black" points="78,-246.25 78,-277.75 186,-277.75 186,-246.25 78,-246.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="94.5" y="-258.3" font-family="Helvetica,sans-Serif" font-size="11.00">Full app state</text>
|
||||
<polygon fill="none" stroke="black" points="186,-246.25 186,-277.75 291,-277.75 291,-246.25 186,-246.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="214.12" y="-258.3" font-family="Helvetica,sans-Serif" font-size="11.00">Required</text>
|
||||
<polygon fill="none" stroke="black" points="291,-246.25 291,-277.75 386.25,-277.75 386.25,-246.25 291,-246.25"/>
|
||||
<text xml:space="preserve" text-anchor="start" x="300" y="-258.3" font-family="Helvetica,sans-Serif" font-size="11.00">Self-contained</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,85 +0,0 @@
|
||||
digraph BuildFlow {
|
||||
// Graph settings
|
||||
rankdir=TB;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
// Title
|
||||
labelloc="t";
|
||||
label="Soleprint - Build Flow";
|
||||
fontsize=16;
|
||||
|
||||
// Styling
|
||||
node [shape=box, style="rounded,filled"];
|
||||
|
||||
// Source
|
||||
subgraph cluster_source {
|
||||
label="Source (spr/)";
|
||||
style=filled;
|
||||
color="#E3F2FD";
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
soleprint_src [label="soleprint/\n(core entry points)", fillcolor="#BBDEFB"];
|
||||
artery_src [label="artery/\n(veins, shunts)", fillcolor="#BBDEFB"];
|
||||
atlas_src [label="atlas/\n(books)", fillcolor="#BBDEFB"];
|
||||
station_src [label="station/\n(tools, monitors)", fillcolor="#BBDEFB"];
|
||||
}
|
||||
|
||||
// Config
|
||||
subgraph cluster_cfg {
|
||||
label="Room Configs (cfg/)";
|
||||
style=filled;
|
||||
color="#FFF8E1";
|
||||
fillcolor="#FFF8E1";
|
||||
|
||||
cfg_standalone [label="cfg/standalone/\nconfig.json\ndata/", fillcolor="#FFECB3"];
|
||||
cfg_amar [label="cfg/amar/\nconfig.json\ndata/\ndocker-compose.yml\n...", fillcolor="#FFECB3"];
|
||||
cfg_other [label="cfg/<room>/\n...", fillcolor="#FFE082", style="rounded,filled,dashed"];
|
||||
}
|
||||
|
||||
// Build tool
|
||||
build [label="build.py", fillcolor="#E1BEE7", shape=hexagon];
|
||||
|
||||
// Commands
|
||||
subgraph cluster_cmds {
|
||||
label="Commands";
|
||||
style=filled;
|
||||
color="#F3E5F5";
|
||||
fillcolor="#F3E5F5";
|
||||
|
||||
cmd1 [label="python build.py dev", fillcolor="#CE93D8"];
|
||||
cmd2 [label="python build.py dev --cfg amar", fillcolor="#CE93D8"];
|
||||
cmd3 [label="python build.py dev --all", fillcolor="#CE93D8"];
|
||||
}
|
||||
|
||||
// Output
|
||||
subgraph cluster_gen {
|
||||
label="Generated Output (gen/)";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
gen_standalone [label="gen/standalone/\n(base soleprint)", fillcolor="#C8E6C9"];
|
||||
gen_amar [label="gen/amar/\n(with amar config)", fillcolor="#C8E6C9"];
|
||||
}
|
||||
|
||||
// Connections
|
||||
soleprint_src -> build;
|
||||
artery_src -> build;
|
||||
atlas_src -> build;
|
||||
station_src -> build;
|
||||
|
||||
cfg_standalone -> build [style=dashed];
|
||||
cfg_amar -> build [style=dashed];
|
||||
|
||||
build -> cmd1 [style=invis];
|
||||
build -> cmd2 [style=invis];
|
||||
build -> cmd3 [style=invis];
|
||||
|
||||
cmd1 -> gen_standalone [label="copies + standalone config"];
|
||||
cmd2 -> gen_amar [label="copies + amar config"];
|
||||
cmd3 -> gen_standalone [style=dashed];
|
||||
cmd3 -> gen_amar [style=dashed];
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: BuildFlow Pages: 1 -->
|
||||
<svg width="854pt" height="452pt"
|
||||
viewBox="0.00 0.00 854.00 452.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 448.25)">
|
||||
<title>BuildFlow</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-448.25 850,-448.25 850,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="423" y="-425.05" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint - Build Flow</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_source</title>
|
||||
<polygon fill="#e3f2fd" stroke="#e3f2fd" points="8,-309.5 8,-389 462,-389 462,-309.5 8,-309.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="235" y="-369.8" font-family="Helvetica,sans-Serif" font-size="16.00">Source (spr/)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_cfg</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="470,-289.75 470,-408.75 838,-408.75 838,-289.75 470,-289.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="654" y="-389.55" font-family="Helvetica,sans-Serif" font-size="16.00">Room Configs (cfg/)</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_cmds</title>
|
||||
<polygon fill="#f3e5f5" stroke="#f3e5f5" points="122,-118.25 122,-197.75 636,-197.75 636,-118.25 122,-118.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="379" y="-178.55" font-family="Helvetica,sans-Serif" font-size="16.00">Commands</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_gen</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="243,-8 243,-87.5 499,-87.5 499,-8 243,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="371" y="-68.3" font-family="Helvetica,sans-Serif" font-size="16.00">Generated Output (gen/)</text>
|
||||
</g>
|
||||
<!-- soleprint_src -->
|
||||
<g id="node1" class="node">
|
||||
<title>soleprint_src</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M123.75,-353.5C123.75,-353.5 28.25,-353.5 28.25,-353.5 22.25,-353.5 16.25,-347.5 16.25,-341.5 16.25,-341.5 16.25,-329.5 16.25,-329.5 16.25,-323.5 22.25,-317.5 28.25,-317.5 28.25,-317.5 123.75,-317.5 123.75,-317.5 129.75,-317.5 135.75,-323.5 135.75,-329.5 135.75,-329.5 135.75,-341.5 135.75,-341.5 135.75,-347.5 129.75,-353.5 123.75,-353.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="76" y="-338.55" font-family="Helvetica,sans-Serif" font-size="11.00">soleprint/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="76" y="-325.05" font-family="Helvetica,sans-Serif" font-size="11.00">(core entry points)</text>
|
||||
</g>
|
||||
<!-- build -->
|
||||
<g id="node8" class="node">
|
||||
<title>build</title>
|
||||
<path fill="#e1bee7" stroke="black" d="M384.69,-248.75C384.69,-248.75 377.55,-254.75 377.55,-254.75 373.98,-257.75 365.75,-260.75 361.09,-260.75 361.09,-260.75 336.91,-260.75 336.91,-260.75 332.25,-260.75 324.02,-257.75 320.45,-254.75 320.45,-254.75 313.31,-248.75 313.31,-248.75 309.74,-245.75 309.74,-239.75 313.31,-236.75 313.31,-236.75 320.45,-230.75 320.45,-230.75 324.02,-227.75 332.25,-224.75 336.91,-224.75 336.91,-224.75 361.09,-224.75 361.09,-224.75 365.75,-224.75 373.98,-227.75 377.55,-230.75 377.55,-230.75 384.69,-236.75 384.69,-236.75 388.26,-239.75 388.26,-245.75 384.69,-248.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="349" y="-239.05" font-family="Helvetica,sans-Serif" font-size="11.00">build.py</text>
|
||||
</g>
|
||||
<!-- soleprint_src->build -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>soleprint_src->build</title>
|
||||
<path fill="none" stroke="black" d="M98.48,-317C111.45,-307.68 128.42,-296.73 145,-289.75 195.92,-268.31 258.4,-256.1 300.69,-249.73"/>
|
||||
<polygon fill="black" stroke="black" points="301.17,-253.2 310.56,-248.3 300.16,-246.27 301.17,-253.2"/>
|
||||
</g>
|
||||
<!-- artery_src -->
|
||||
<g id="node2" class="node">
|
||||
<title>artery_src</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M240.25,-353.5C240.25,-353.5 165.75,-353.5 165.75,-353.5 159.75,-353.5 153.75,-347.5 153.75,-341.5 153.75,-341.5 153.75,-329.5 153.75,-329.5 153.75,-323.5 159.75,-317.5 165.75,-317.5 165.75,-317.5 240.25,-317.5 240.25,-317.5 246.25,-317.5 252.25,-323.5 252.25,-329.5 252.25,-329.5 252.25,-341.5 252.25,-341.5 252.25,-347.5 246.25,-353.5 240.25,-353.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="203" y="-338.55" font-family="Helvetica,sans-Serif" font-size="11.00">artery/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="203" y="-325.05" font-family="Helvetica,sans-Serif" font-size="11.00">(veins, shunts)</text>
|
||||
</g>
|
||||
<!-- artery_src->build -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>artery_src->build</title>
|
||||
<path fill="none" stroke="black" d="M223.56,-317.21C234.37,-308.5 248.04,-298.05 261,-289.75 277.08,-279.46 295.71,-269.46 311.69,-261.43"/>
|
||||
<polygon fill="black" stroke="black" points="312.98,-264.7 320.39,-257.13 309.87,-258.42 312.98,-264.7"/>
|
||||
</g>
|
||||
<!-- atlas_src -->
|
||||
<g id="node3" class="node">
|
||||
<title>atlas_src</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M315.62,-353.5C315.62,-353.5 282.38,-353.5 282.38,-353.5 276.38,-353.5 270.38,-347.5 270.38,-341.5 270.38,-341.5 270.38,-329.5 270.38,-329.5 270.38,-323.5 276.38,-317.5 282.38,-317.5 282.38,-317.5 315.62,-317.5 315.62,-317.5 321.62,-317.5 327.62,-323.5 327.62,-329.5 327.62,-329.5 327.62,-341.5 327.62,-341.5 327.62,-347.5 321.62,-353.5 315.62,-353.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="299" y="-338.55" font-family="Helvetica,sans-Serif" font-size="11.00">atlas/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="299" y="-325.05" font-family="Helvetica,sans-Serif" font-size="11.00">(books)</text>
|
||||
</g>
|
||||
<!-- atlas_src->build -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>atlas_src->build</title>
|
||||
<path fill="none" stroke="black" d="M308.64,-317C315.83,-303.95 325.8,-285.86 334.03,-270.93"/>
|
||||
<polygon fill="black" stroke="black" points="336.9,-272.97 338.66,-262.52 330.77,-269.59 336.9,-272.97"/>
|
||||
</g>
|
||||
<!-- station_src -->
|
||||
<g id="node4" class="node">
|
||||
<title>station_src</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M442.12,-353.5C442.12,-353.5 357.88,-353.5 357.88,-353.5 351.88,-353.5 345.88,-347.5 345.88,-341.5 345.88,-341.5 345.88,-329.5 345.88,-329.5 345.88,-323.5 351.88,-317.5 357.88,-317.5 357.88,-317.5 442.12,-317.5 442.12,-317.5 448.12,-317.5 454.12,-323.5 454.12,-329.5 454.12,-329.5 454.12,-341.5 454.12,-341.5 454.12,-347.5 448.12,-353.5 442.12,-353.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="400" y="-338.55" font-family="Helvetica,sans-Serif" font-size="11.00">station/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="400" y="-325.05" font-family="Helvetica,sans-Serif" font-size="11.00">(tools, monitors)</text>
|
||||
</g>
|
||||
<!-- station_src->build -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>station_src->build</title>
|
||||
<path fill="none" stroke="black" d="M390.17,-317C382.83,-303.95 372.67,-285.86 364.27,-270.93"/>
|
||||
<polygon fill="black" stroke="black" points="367.5,-269.52 359.54,-262.51 361.39,-272.95 367.5,-269.52"/>
|
||||
</g>
|
||||
<!-- cfg_standalone -->
|
||||
<g id="node5" class="node">
|
||||
<title>cfg_standalone</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M566.38,-359.75C566.38,-359.75 489.62,-359.75 489.62,-359.75 483.62,-359.75 477.62,-353.75 477.62,-347.75 477.62,-347.75 477.62,-323.25 477.62,-323.25 477.62,-317.25 483.62,-311.25 489.62,-311.25 489.62,-311.25 566.38,-311.25 566.38,-311.25 572.38,-311.25 578.38,-317.25 578.38,-323.25 578.38,-323.25 578.38,-347.75 578.38,-347.75 578.38,-353.75 572.38,-359.75 566.38,-359.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="528" y="-345.3" font-family="Helvetica,sans-Serif" font-size="11.00">cfg/standalone/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="528" y="-331.8" font-family="Helvetica,sans-Serif" font-size="11.00">config.json</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="528" y="-318.3" font-family="Helvetica,sans-Serif" font-size="11.00">data/</text>
|
||||
</g>
|
||||
<!-- cfg_standalone->build -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>cfg_standalone->build</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M498.41,-310.84C488.46,-303.52 477.07,-295.79 466,-289.75 441.97,-276.62 413.39,-265.31 390.49,-257.19"/>
|
||||
<polygon fill="black" stroke="black" points="391.78,-253.94 381.18,-253.97 389.48,-260.55 391.78,-253.94"/>
|
||||
</g>
|
||||
<!-- cfg_amar -->
|
||||
<g id="node6" class="node">
|
||||
<title>cfg_amar</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M713.62,-373.25C713.62,-373.25 608.38,-373.25 608.38,-373.25 602.38,-373.25 596.38,-367.25 596.38,-361.25 596.38,-361.25 596.38,-309.75 596.38,-309.75 596.38,-303.75 602.38,-297.75 608.38,-297.75 608.38,-297.75 713.62,-297.75 713.62,-297.75 719.62,-297.75 725.62,-303.75 725.62,-309.75 725.62,-309.75 725.62,-361.25 725.62,-361.25 725.62,-367.25 719.62,-373.25 713.62,-373.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="661" y="-358.8" font-family="Helvetica,sans-Serif" font-size="11.00">cfg/amar/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="661" y="-345.3" font-family="Helvetica,sans-Serif" font-size="11.00">config.json</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="661" y="-331.8" font-family="Helvetica,sans-Serif" font-size="11.00">data/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="661" y="-318.3" font-family="Helvetica,sans-Serif" font-size="11.00">docker-compose.yml</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="661" y="-304.8" font-family="Helvetica,sans-Serif" font-size="11.00">...</text>
|
||||
</g>
|
||||
<!-- cfg_amar->build -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>cfg_amar->build</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M603.83,-297.29C598.26,-294.48 592.6,-291.91 587,-289.75 524.46,-265.68 447.64,-253.76 398.5,-248.18"/>
|
||||
<polygon fill="black" stroke="black" points="399.06,-244.72 388.74,-247.12 398.31,-251.68 399.06,-244.72"/>
|
||||
</g>
|
||||
<!-- cfg_other -->
|
||||
<g id="node7" class="node">
|
||||
<title>cfg_other</title>
|
||||
<path fill="#ffe082" stroke="black" stroke-dasharray="5,2" d="M818.25,-353.5C818.25,-353.5 755.75,-353.5 755.75,-353.5 749.75,-353.5 743.75,-347.5 743.75,-341.5 743.75,-341.5 743.75,-329.5 743.75,-329.5 743.75,-323.5 749.75,-317.5 755.75,-317.5 755.75,-317.5 818.25,-317.5 818.25,-317.5 824.25,-317.5 830.25,-323.5 830.25,-329.5 830.25,-329.5 830.25,-341.5 830.25,-341.5 830.25,-347.5 824.25,-353.5 818.25,-353.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="787" y="-338.55" font-family="Helvetica,sans-Serif" font-size="11.00">cfg/<room>/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="787" y="-325.05" font-family="Helvetica,sans-Serif" font-size="11.00">...</text>
|
||||
</g>
|
||||
<!-- cmd1 -->
|
||||
<g id="node9" class="node">
|
||||
<title>cmd1</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M243.75,-162.25C243.75,-162.25 142.25,-162.25 142.25,-162.25 136.25,-162.25 130.25,-156.25 130.25,-150.25 130.25,-150.25 130.25,-138.25 130.25,-138.25 130.25,-132.25 136.25,-126.25 142.25,-126.25 142.25,-126.25 243.75,-126.25 243.75,-126.25 249.75,-126.25 255.75,-132.25 255.75,-138.25 255.75,-138.25 255.75,-150.25 255.75,-150.25 255.75,-156.25 249.75,-162.25 243.75,-162.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="193" y="-140.55" font-family="Helvetica,sans-Serif" font-size="11.00">python build.py dev</text>
|
||||
</g>
|
||||
<!-- build->cmd1 -->
|
||||
<!-- cmd2 -->
|
||||
<g id="node10" class="node">
|
||||
<title>cmd2</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M615.75,-162.25C615.75,-162.25 454.25,-162.25 454.25,-162.25 448.25,-162.25 442.25,-156.25 442.25,-150.25 442.25,-150.25 442.25,-138.25 442.25,-138.25 442.25,-132.25 448.25,-126.25 454.25,-126.25 454.25,-126.25 615.75,-126.25 615.75,-126.25 621.75,-126.25 627.75,-132.25 627.75,-138.25 627.75,-138.25 627.75,-150.25 627.75,-150.25 627.75,-156.25 621.75,-162.25 615.75,-162.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="535" y="-140.55" font-family="Helvetica,sans-Serif" font-size="11.00">python build.py dev --cfg amar</text>
|
||||
</g>
|
||||
<!-- build->cmd2 -->
|
||||
<!-- cmd3 -->
|
||||
<g id="node11" class="node">
|
||||
<title>cmd3</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M411.75,-162.25C411.75,-162.25 286.25,-162.25 286.25,-162.25 280.25,-162.25 274.25,-156.25 274.25,-150.25 274.25,-150.25 274.25,-138.25 274.25,-138.25 274.25,-132.25 280.25,-126.25 286.25,-126.25 286.25,-126.25 411.75,-126.25 411.75,-126.25 417.75,-126.25 423.75,-132.25 423.75,-138.25 423.75,-138.25 423.75,-150.25 423.75,-150.25 423.75,-156.25 417.75,-162.25 411.75,-162.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="349" y="-140.55" font-family="Helvetica,sans-Serif" font-size="11.00">python build.py dev --all</text>
|
||||
</g>
|
||||
<!-- build->cmd3 -->
|
||||
<!-- gen_standalone -->
|
||||
<g id="node12" class="node">
|
||||
<title>gen_standalone</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M343.25,-52C343.25,-52 262.75,-52 262.75,-52 256.75,-52 250.75,-46 250.75,-40 250.75,-40 250.75,-28 250.75,-28 250.75,-22 256.75,-16 262.75,-16 262.75,-16 343.25,-16 343.25,-16 349.25,-16 355.25,-22 355.25,-28 355.25,-28 355.25,-40 355.25,-40 355.25,-46 349.25,-52 343.25,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="303" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00">gen/standalone/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="303" y="-23.55" font-family="Helvetica,sans-Serif" font-size="11.00">(base soleprint)</text>
|
||||
</g>
|
||||
<!-- cmd1->gen_standalone -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>cmd1->gen_standalone</title>
|
||||
<path fill="none" stroke="black" d="M190.27,-126.13C189.61,-116.45 190.36,-104.51 196,-95.5 206.41,-78.87 223.15,-66.38 240.33,-57.2"/>
|
||||
<polygon fill="black" stroke="black" points="241.69,-60.43 249.09,-52.85 238.58,-54.16 241.69,-60.43"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="262" y="-98.75" font-family="Helvetica,sans-Serif" font-size="10.00">copies + standalone config</text>
|
||||
</g>
|
||||
<!-- gen_amar -->
|
||||
<g id="node13" class="node">
|
||||
<title>gen_amar</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M478.62,-52C478.62,-52 385.38,-52 385.38,-52 379.38,-52 373.38,-46 373.38,-40 373.38,-40 373.38,-28 373.38,-28 373.38,-22 379.38,-16 385.38,-16 385.38,-16 478.62,-16 478.62,-16 484.62,-16 490.62,-22 490.62,-28 490.62,-28 490.62,-40 490.62,-40 490.62,-46 484.62,-52 478.62,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="432" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00">gen/amar/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="432" y="-23.55" font-family="Helvetica,sans-Serif" font-size="11.00">(with amar config)</text>
|
||||
</g>
|
||||
<!-- cmd2->gen_amar -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>cmd2->gen_amar</title>
|
||||
<path fill="none" stroke="black" d="M518.45,-125.86C501.63,-108.18 475.4,-80.61 456.24,-60.47"/>
|
||||
<polygon fill="black" stroke="black" points="458.98,-58.28 449.55,-53.45 453.91,-63.1 458.98,-58.28"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="553.43" y="-98.75" font-family="Helvetica,sans-Serif" font-size="10.00">copies + amar config</text>
|
||||
</g>
|
||||
<!-- cmd3->gen_standalone -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>cmd3->gen_standalone</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M343.29,-125.84C340.18,-116.72 336.13,-105.41 332,-95.5 327.41,-84.49 321.86,-72.6 316.84,-62.31"/>
|
||||
<polygon fill="black" stroke="black" points="320.11,-61.02 312.54,-53.61 313.83,-64.13 320.11,-61.02"/>
|
||||
</g>
|
||||
<!-- cmd3->gen_amar -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>cmd3->gen_amar</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M362.34,-125.86C375.71,-108.42 396.46,-81.35 411.84,-61.29"/>
|
||||
<polygon fill="black" stroke="black" points="414.47,-63.62 417.78,-53.55 408.91,-59.36 414.47,-63.62"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,83 +0,0 @@
|
||||
digraph RoomConfig {
|
||||
// Graph settings
|
||||
rankdir=TB;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
// Title
|
||||
labelloc="t";
|
||||
label="Soleprint - Room Configuration Structure";
|
||||
fontsize=16;
|
||||
|
||||
// Styling
|
||||
node [shape=box, style="rounded,filled"];
|
||||
|
||||
// Room config structure
|
||||
subgraph cluster_room {
|
||||
label="cfg/<room>/";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
config_json [label="config.json\n\nFramework branding\nTerminology customization\n(can rebrand soleprint)", fillcolor="#C8E6C9"];
|
||||
|
||||
subgraph cluster_data {
|
||||
label="data/";
|
||||
style=filled;
|
||||
color="#DCEDC8";
|
||||
fillcolor="#DCEDC8";
|
||||
|
||||
veins_json [label="veins.json", fillcolor="#AED581"];
|
||||
shunts_json [label="shunts.json", fillcolor="#AED581"];
|
||||
depots_json [label="depots.json", fillcolor="#AED581"];
|
||||
rooms_json [label="rooms.json", fillcolor="#AED581"];
|
||||
}
|
||||
|
||||
subgraph cluster_docker {
|
||||
label="Docker";
|
||||
style=filled;
|
||||
color="#FFECB3";
|
||||
fillcolor="#FFECB3";
|
||||
|
||||
docker_compose [label="docker-compose.yml", fillcolor="#FFE082"];
|
||||
dockerfile_be [label="Dockerfile.backend", fillcolor="#FFE082"];
|
||||
dockerfile_fe [label="Dockerfile.frontend", fillcolor="#FFE082"];
|
||||
env_example [label=".env.example", fillcolor="#FFE082"];
|
||||
}
|
||||
|
||||
subgraph cluster_soleprint {
|
||||
label="soleprint/";
|
||||
style=filled;
|
||||
color="#E1BEE7";
|
||||
fillcolor="#E1BEE7";
|
||||
|
||||
spr_compose [label="docker-compose.yml\n(soleprint for this room)", fillcolor="#CE93D8"];
|
||||
spr_env [label=".env", fillcolor="#CE93D8"];
|
||||
}
|
||||
|
||||
subgraph cluster_extras {
|
||||
label="Room-specific";
|
||||
style=filled;
|
||||
color="#B2EBF2";
|
||||
fillcolor="#B2EBF2";
|
||||
|
||||
databrowse [label="databrowse/depot/\n(DB schema)", fillcolor="#80DEEA"];
|
||||
tester [label="tester/tests/\n(Room tests)", fillcolor="#80DEEA"];
|
||||
monitors [label="monitors/\n(Room monitors)", fillcolor="#80DEEA"];
|
||||
models [label="models/\n(Room models)", fillcolor="#80DEEA"];
|
||||
}
|
||||
}
|
||||
|
||||
// Examples
|
||||
subgraph cluster_examples {
|
||||
label="Examples";
|
||||
style=dashed;
|
||||
color=gray;
|
||||
|
||||
standalone [label="cfg/standalone/\n\nBase soleprint\nGeneric veins\nNo docker-compose", fillcolor="#F5F5F5"];
|
||||
|
||||
amar [label="cfg/amar/\n\nAMAR veterinary app\namar + mercadopago shunts\nFull Docker setup\nCustom monitors (turnos)", fillcolor="#F5F5F5"];
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: RoomConfig Pages: 1 -->
|
||||
<svg width="2212pt" height="193pt"
|
||||
viewBox="0.00 0.00 2212.00 193.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 188.75)">
|
||||
<title>RoomConfig</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-188.75 2208,-188.75 2208,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1102" y="-165.55" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint - Room Configuration Structure</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_room</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="8,-14.75 8,-149.25 1854,-149.25 1854,-14.75 8,-14.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="931" y="-130.05" font-family="Helvetica,sans-Serif" font-size="16.00">cfg/<room>/</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_data</title>
|
||||
<polygon fill="#dcedc8" stroke="#dcedc8" points="16,-34.25 16,-113.75 392,-113.75 392,-34.25 16,-34.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="204" y="-94.55" font-family="Helvetica,sans-Serif" font-size="16.00">data/</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_docker</title>
|
||||
<polygon fill="#ffecb3" stroke="#ffecb3" points="400,-34.25 400,-113.75 932,-113.75 932,-34.25 400,-34.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="666" y="-94.55" font-family="Helvetica,sans-Serif" font-size="16.00">Docker</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_soleprint</title>
|
||||
<polygon fill="#e1bee7" stroke="#e1bee7" points="940,-34.25 940,-113.75 1176,-113.75 1176,-34.25 940,-34.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1058" y="-94.55" font-family="Helvetica,sans-Serif" font-size="16.00">soleprint/</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_extras</title>
|
||||
<polygon fill="#b2ebf2" stroke="#b2ebf2" points="1184,-34.25 1184,-113.75 1672,-113.75 1672,-34.25 1184,-34.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1428" y="-94.55" font-family="Helvetica,sans-Serif" font-size="16.00">Room-specific</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_examples</title>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="1862,-8 1862,-140 2196,-140 2196,-8 1862,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2029" y="-120.8" font-family="Helvetica,sans-Serif" font-size="16.00">Examples</text>
|
||||
</g>
|
||||
<!-- config_json -->
|
||||
<g id="node1" class="node">
|
||||
<title>config_json</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M1833.5,-97.75C1833.5,-97.75 1694.5,-97.75 1694.5,-97.75 1688.5,-97.75 1682.5,-91.75 1682.5,-85.75 1682.5,-85.75 1682.5,-34.75 1682.5,-34.75 1682.5,-28.75 1688.5,-22.75 1694.5,-22.75 1694.5,-22.75 1833.5,-22.75 1833.5,-22.75 1839.5,-22.75 1845.5,-28.75 1845.5,-34.75 1845.5,-34.75 1845.5,-85.75 1845.5,-85.75 1845.5,-91.75 1839.5,-97.75 1833.5,-97.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1764" y="-83.3" font-family="Helvetica,sans-Serif" font-size="11.00">config.json</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1764" y="-56.8" font-family="Helvetica,sans-Serif" font-size="11.00">Framework branding</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1764" y="-43.3" font-family="Helvetica,sans-Serif" font-size="11.00">Terminology customization</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1764" y="-29.8" font-family="Helvetica,sans-Serif" font-size="11.00">(can rebrand soleprint)</text>
|
||||
</g>
|
||||
<!-- veins_json -->
|
||||
<g id="node2" class="node">
|
||||
<title>veins_json</title>
|
||||
<path fill="#aed581" stroke="black" d="M83.75,-78.25C83.75,-78.25 36.25,-78.25 36.25,-78.25 30.25,-78.25 24.25,-72.25 24.25,-66.25 24.25,-66.25 24.25,-54.25 24.25,-54.25 24.25,-48.25 30.25,-42.25 36.25,-42.25 36.25,-42.25 83.75,-42.25 83.75,-42.25 89.75,-42.25 95.75,-48.25 95.75,-54.25 95.75,-54.25 95.75,-66.25 95.75,-66.25 95.75,-72.25 89.75,-78.25 83.75,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="60" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">veins.json</text>
|
||||
</g>
|
||||
<!-- shunts_json -->
|
||||
<g id="node3" class="node">
|
||||
<title>shunts_json</title>
|
||||
<path fill="#aed581" stroke="black" d="M180.5,-78.25C180.5,-78.25 125.5,-78.25 125.5,-78.25 119.5,-78.25 113.5,-72.25 113.5,-66.25 113.5,-66.25 113.5,-54.25 113.5,-54.25 113.5,-48.25 119.5,-42.25 125.5,-42.25 125.5,-42.25 180.5,-42.25 180.5,-42.25 186.5,-42.25 192.5,-48.25 192.5,-54.25 192.5,-54.25 192.5,-66.25 192.5,-66.25 192.5,-72.25 186.5,-78.25 180.5,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="153" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">shunts.json</text>
|
||||
</g>
|
||||
<!-- depots_json -->
|
||||
<g id="node4" class="node">
|
||||
<title>depots_json</title>
|
||||
<path fill="#aed581" stroke="black" d="M277.88,-78.25C277.88,-78.25 222.12,-78.25 222.12,-78.25 216.12,-78.25 210.12,-72.25 210.12,-66.25 210.12,-66.25 210.12,-54.25 210.12,-54.25 210.12,-48.25 216.12,-42.25 222.12,-42.25 222.12,-42.25 277.88,-42.25 277.88,-42.25 283.88,-42.25 289.88,-48.25 289.88,-54.25 289.88,-54.25 289.88,-66.25 289.88,-66.25 289.88,-72.25 283.88,-78.25 277.88,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="250" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">depots.json</text>
|
||||
</g>
|
||||
<!-- rooms_json -->
|
||||
<g id="node5" class="node">
|
||||
<title>rooms_json</title>
|
||||
<path fill="#aed581" stroke="black" d="M372.38,-78.25C372.38,-78.25 319.62,-78.25 319.62,-78.25 313.62,-78.25 307.62,-72.25 307.62,-66.25 307.62,-66.25 307.62,-54.25 307.62,-54.25 307.62,-48.25 313.62,-42.25 319.62,-42.25 319.62,-42.25 372.38,-42.25 372.38,-42.25 378.38,-42.25 384.38,-48.25 384.38,-54.25 384.38,-54.25 384.38,-66.25 384.38,-66.25 384.38,-72.25 378.38,-78.25 372.38,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="346" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">rooms.json</text>
|
||||
</g>
|
||||
<!-- docker_compose -->
|
||||
<g id="node6" class="node">
|
||||
<title>docker_compose</title>
|
||||
<path fill="#ffe082" stroke="black" d="M525.62,-78.25C525.62,-78.25 420.38,-78.25 420.38,-78.25 414.38,-78.25 408.38,-72.25 408.38,-66.25 408.38,-66.25 408.38,-54.25 408.38,-54.25 408.38,-48.25 414.38,-42.25 420.38,-42.25 420.38,-42.25 525.62,-42.25 525.62,-42.25 531.62,-42.25 537.62,-48.25 537.62,-54.25 537.62,-54.25 537.62,-66.25 537.62,-66.25 537.62,-72.25 531.62,-78.25 525.62,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="473" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">docker-compose.yml</text>
|
||||
</g>
|
||||
<!-- dockerfile_be -->
|
||||
<g id="node7" class="node">
|
||||
<title>dockerfile_be</title>
|
||||
<path fill="#ffe082" stroke="black" d="M664.12,-78.25C664.12,-78.25 567.88,-78.25 567.88,-78.25 561.88,-78.25 555.88,-72.25 555.88,-66.25 555.88,-66.25 555.88,-54.25 555.88,-54.25 555.88,-48.25 561.88,-42.25 567.88,-42.25 567.88,-42.25 664.12,-42.25 664.12,-42.25 670.12,-42.25 676.12,-48.25 676.12,-54.25 676.12,-54.25 676.12,-66.25 676.12,-66.25 676.12,-72.25 670.12,-78.25 664.12,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="616" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">Dockerfile.backend</text>
|
||||
</g>
|
||||
<!-- dockerfile_fe -->
|
||||
<g id="node8" class="node">
|
||||
<title>dockerfile_fe</title>
|
||||
<path fill="#ffe082" stroke="black" d="M803.5,-78.25C803.5,-78.25 706.5,-78.25 706.5,-78.25 700.5,-78.25 694.5,-72.25 694.5,-66.25 694.5,-66.25 694.5,-54.25 694.5,-54.25 694.5,-48.25 700.5,-42.25 706.5,-42.25 706.5,-42.25 803.5,-42.25 803.5,-42.25 809.5,-42.25 815.5,-48.25 815.5,-54.25 815.5,-54.25 815.5,-66.25 815.5,-66.25 815.5,-72.25 809.5,-78.25 803.5,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="755" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">Dockerfile.frontend</text>
|
||||
</g>
|
||||
<!-- env_example -->
|
||||
<g id="node9" class="node">
|
||||
<title>env_example</title>
|
||||
<path fill="#ffe082" stroke="black" d="M912.12,-78.25C912.12,-78.25 845.88,-78.25 845.88,-78.25 839.88,-78.25 833.88,-72.25 833.88,-66.25 833.88,-66.25 833.88,-54.25 833.88,-54.25 833.88,-48.25 839.88,-42.25 845.88,-42.25 845.88,-42.25 912.12,-42.25 912.12,-42.25 918.12,-42.25 924.12,-48.25 924.12,-54.25 924.12,-54.25 924.12,-66.25 924.12,-66.25 924.12,-72.25 918.12,-78.25 912.12,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="879" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">.env.example</text>
|
||||
</g>
|
||||
<!-- spr_compose -->
|
||||
<g id="node10" class="node">
|
||||
<title>spr_compose</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M1084,-78.25C1084,-78.25 960,-78.25 960,-78.25 954,-78.25 948,-72.25 948,-66.25 948,-66.25 948,-54.25 948,-54.25 948,-48.25 954,-42.25 960,-42.25 960,-42.25 1084,-42.25 1084,-42.25 1090,-42.25 1096,-48.25 1096,-54.25 1096,-54.25 1096,-66.25 1096,-66.25 1096,-72.25 1090,-78.25 1084,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1022" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">docker-compose.yml</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1022" y="-49.8" font-family="Helvetica,sans-Serif" font-size="11.00">(soleprint for this room)</text>
|
||||
</g>
|
||||
<!-- spr_env -->
|
||||
<g id="node11" class="node">
|
||||
<title>spr_env</title>
|
||||
<path fill="#ce93d8" stroke="black" d="M1156,-78.25C1156,-78.25 1126,-78.25 1126,-78.25 1120,-78.25 1114,-72.25 1114,-66.25 1114,-66.25 1114,-54.25 1114,-54.25 1114,-48.25 1120,-42.25 1126,-42.25 1126,-42.25 1156,-42.25 1156,-42.25 1162,-42.25 1168,-48.25 1168,-54.25 1168,-54.25 1168,-66.25 1168,-66.25 1168,-72.25 1162,-78.25 1156,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1141" y="-56.55" font-family="Helvetica,sans-Serif" font-size="11.00">.env</text>
|
||||
</g>
|
||||
<!-- databrowse -->
|
||||
<g id="node12" class="node">
|
||||
<title>databrowse</title>
|
||||
<path fill="#80deea" stroke="black" d="M1299.75,-78.25C1299.75,-78.25 1204.25,-78.25 1204.25,-78.25 1198.25,-78.25 1192.25,-72.25 1192.25,-66.25 1192.25,-66.25 1192.25,-54.25 1192.25,-54.25 1192.25,-48.25 1198.25,-42.25 1204.25,-42.25 1204.25,-42.25 1299.75,-42.25 1299.75,-42.25 1305.75,-42.25 1311.75,-48.25 1311.75,-54.25 1311.75,-54.25 1311.75,-66.25 1311.75,-66.25 1311.75,-72.25 1305.75,-78.25 1299.75,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1252" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">databrowse/depot/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1252" y="-49.8" font-family="Helvetica,sans-Serif" font-size="11.00">(DB schema)</text>
|
||||
</g>
|
||||
<!-- tester -->
|
||||
<g id="node13" class="node">
|
||||
<title>tester</title>
|
||||
<path fill="#80deea" stroke="black" d="M1406,-78.25C1406,-78.25 1342,-78.25 1342,-78.25 1336,-78.25 1330,-72.25 1330,-66.25 1330,-66.25 1330,-54.25 1330,-54.25 1330,-48.25 1336,-42.25 1342,-42.25 1342,-42.25 1406,-42.25 1406,-42.25 1412,-42.25 1418,-48.25 1418,-54.25 1418,-54.25 1418,-66.25 1418,-66.25 1418,-72.25 1412,-78.25 1406,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1374" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">tester/tests/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1374" y="-49.8" font-family="Helvetica,sans-Serif" font-size="11.00">(Room tests)</text>
|
||||
</g>
|
||||
<!-- monitors -->
|
||||
<g id="node14" class="node">
|
||||
<title>monitors</title>
|
||||
<path fill="#80deea" stroke="black" d="M1533.5,-78.25C1533.5,-78.25 1448.5,-78.25 1448.5,-78.25 1442.5,-78.25 1436.5,-72.25 1436.5,-66.25 1436.5,-66.25 1436.5,-54.25 1436.5,-54.25 1436.5,-48.25 1442.5,-42.25 1448.5,-42.25 1448.5,-42.25 1533.5,-42.25 1533.5,-42.25 1539.5,-42.25 1545.5,-48.25 1545.5,-54.25 1545.5,-54.25 1545.5,-66.25 1545.5,-66.25 1545.5,-72.25 1539.5,-78.25 1533.5,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1491" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">monitors/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1491" y="-49.8" font-family="Helvetica,sans-Serif" font-size="11.00">(Room monitors)</text>
|
||||
</g>
|
||||
<!-- models -->
|
||||
<g id="node15" class="node">
|
||||
<title>models</title>
|
||||
<path fill="#80deea" stroke="black" d="M1652,-78.25C1652,-78.25 1576,-78.25 1576,-78.25 1570,-78.25 1564,-72.25 1564,-66.25 1564,-66.25 1564,-54.25 1564,-54.25 1564,-48.25 1570,-42.25 1576,-42.25 1576,-42.25 1652,-42.25 1652,-42.25 1658,-42.25 1664,-48.25 1664,-54.25 1664,-54.25 1664,-66.25 1664,-66.25 1664,-72.25 1658,-78.25 1652,-78.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1614" y="-63.3" font-family="Helvetica,sans-Serif" font-size="11.00">models/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1614" y="-49.8" font-family="Helvetica,sans-Serif" font-size="11.00">(Room models)</text>
|
||||
</g>
|
||||
<!-- standalone -->
|
||||
<g id="node16" class="node">
|
||||
<title>standalone</title>
|
||||
<path fill="#f5f5f5" stroke="black" d="M1982,-97.75C1982,-97.75 1882,-97.75 1882,-97.75 1876,-97.75 1870,-91.75 1870,-85.75 1870,-85.75 1870,-34.75 1870,-34.75 1870,-28.75 1876,-22.75 1882,-22.75 1882,-22.75 1982,-22.75 1982,-22.75 1988,-22.75 1994,-28.75 1994,-34.75 1994,-34.75 1994,-85.75 1994,-85.75 1994,-91.75 1988,-97.75 1982,-97.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1932" y="-83.3" font-family="Helvetica,sans-Serif" font-size="11.00">cfg/standalone/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1932" y="-56.8" font-family="Helvetica,sans-Serif" font-size="11.00">Base soleprint</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1932" y="-43.3" font-family="Helvetica,sans-Serif" font-size="11.00">Generic veins</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1932" y="-29.8" font-family="Helvetica,sans-Serif" font-size="11.00">No docker-compose</text>
|
||||
</g>
|
||||
<!-- amar -->
|
||||
<g id="node17" class="node">
|
||||
<title>amar</title>
|
||||
<path fill="#f5f5f5" stroke="black" d="M2176.25,-104.5C2176.25,-104.5 2023.75,-104.5 2023.75,-104.5 2017.75,-104.5 2011.75,-98.5 2011.75,-92.5 2011.75,-92.5 2011.75,-28 2011.75,-28 2011.75,-22 2017.75,-16 2023.75,-16 2023.75,-16 2176.25,-16 2176.25,-16 2182.25,-16 2188.25,-22 2188.25,-28 2188.25,-28 2188.25,-92.5 2188.25,-92.5 2188.25,-98.5 2182.25,-104.5 2176.25,-104.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2100" y="-90.05" font-family="Helvetica,sans-Serif" font-size="11.00">cfg/amar/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2100" y="-63.55" font-family="Helvetica,sans-Serif" font-size="11.00">AMAR veterinary app</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2100" y="-50.05" font-family="Helvetica,sans-Serif" font-size="11.00">amar + mercadopago shunts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2100" y="-36.55" font-family="Helvetica,sans-Serif" font-size="11.00">Full Docker setup</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="2100" y="-23.05" font-family="Helvetica,sans-Serif" font-size="11.00">Custom monitors (turnos)</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,217 +0,0 @@
|
||||
# Sidebar Injection Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
The soleprint sidebar is injected into managed app pages using a hybrid nginx + JavaScript approach. This allows any frontend framework (React, Next.js, static HTML) to receive the sidebar without code modifications.
|
||||
|
||||
## How It Works
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Browser Request │
|
||||
│ http://room.spr.local.ar/ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Nginx │
|
||||
│ │
|
||||
│ 1. Routes /spr/* → soleprint:PORT (sidebar assets + API) │
|
||||
│ 2. Routes /* → frontend:PORT (app pages) │
|
||||
│ 3. Injects CSS+JS into HTML responses via sub_filter │
|
||||
│ │
|
||||
│ sub_filter '</head>' │
|
||||
│ '<link rel="stylesheet" href="/spr/sidebar.css"> │
|
||||
│ <script src="/spr/sidebar.js" defer></script></head>'; │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Browser Renders │
|
||||
│ │
|
||||
│ 1. Page loads with injected CSS (sidebar styles ready) │
|
||||
│ 2. sidebar.js executes (deferred, after DOM ready) │
|
||||
│ 3. JS fetches /spr/api/sidebar/config (room name, auth, etc) │
|
||||
│ 4. JS creates sidebar DOM elements and injects into page │
|
||||
│ 5. Sidebar appears on left side, pushes content with margin │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### Why nginx sub_filter instead of modifying app code?
|
||||
|
||||
- **Framework agnostic**: Works with any frontend (Next.js, React, Vue, static HTML)
|
||||
- **No app changes needed**: The managed app doesn't need to know about soleprint
|
||||
- **Easy to disable**: Just access `room.local.ar` instead of `room.spr.local.ar`
|
||||
|
||||
### Why inject into `</head>` instead of `</body>`?
|
||||
|
||||
Next.js and other streaming SSR frameworks may not include `</body>` in the initial HTML response. The `</head>` tag is always present, so we inject both CSS and JS there using `defer` to ensure JS runs after DOM is ready.
|
||||
|
||||
### Why JavaScript injection instead of iframe?
|
||||
|
||||
- **No iframe isolation issues**: Sidebar can interact with page if needed
|
||||
- **Better UX**: No double scrollbars, native feel
|
||||
- **Simpler CSS**: Just push content with `margin-left`
|
||||
|
||||
## Nginx Configuration
|
||||
|
||||
There are two options for local development:
|
||||
|
||||
### Option 1: Docker Nginx (Recommended for portability)
|
||||
|
||||
Each room includes a docker-compose.nginx.yml that runs nginx in a container.
|
||||
|
||||
```bash
|
||||
# Add to /etc/hosts
|
||||
127.0.0.1 sample.spr.local.ar sample.local.ar
|
||||
|
||||
# Start room with nginx
|
||||
cd gen/<room>/soleprint
|
||||
docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d
|
||||
```
|
||||
|
||||
The nginx config in `cfg/<room>/soleprint/nginx/local.conf` uses docker service names:
|
||||
|
||||
```nginx
|
||||
location /spr/ {
|
||||
proxy_pass http://soleprint:8000/;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://frontend:80;
|
||||
# ... sub_filter for sidebar injection
|
||||
}
|
||||
```
|
||||
|
||||
**Pros**: Portable, no system dependencies, isolated per room
|
||||
**Cons**: Only one room can use port 80 at a time
|
||||
|
||||
### Option 2: System Nginx (For running multiple rooms)
|
||||
|
||||
If you need multiple rooms running simultaneously, use your system's nginx.
|
||||
|
||||
1. Install nginx: `sudo apt install nginx`
|
||||
|
||||
2. Add hosts entries for all rooms:
|
||||
```
|
||||
# /etc/hosts
|
||||
127.0.0.1 amar.spr.local.ar amar.local.ar
|
||||
127.0.0.1 dlt.spr.local.ar dlt.local.ar
|
||||
127.0.0.1 sample.spr.local.ar sample.local.ar
|
||||
```
|
||||
|
||||
3. Create config in `/etc/nginx/sites-enabled/spr_local.conf`:
|
||||
|
||||
```nginx
|
||||
# room.spr.local.ar - app with sidebar
|
||||
server {
|
||||
listen 80;
|
||||
server_name room.spr.local.ar;
|
||||
|
||||
# Soleprint assets and API
|
||||
location /spr/ {
|
||||
proxy_pass http://127.0.0.1:SOLEPRINT_PORT/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Backend API (if applicable)
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:BACKEND_PORT/api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Frontend with sidebar injection
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:FRONTEND_PORT;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Accept-Encoding ""; # Required for sub_filter
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# Inject sidebar
|
||||
sub_filter '</head>' '<link rel="stylesheet" href="/spr/sidebar.css"><script src="/spr/sidebar.js" defer></script></head>';
|
||||
sub_filter_once off;
|
||||
sub_filter_types text/html;
|
||||
}
|
||||
}
|
||||
|
||||
# room.local.ar - app without sidebar (direct access)
|
||||
server {
|
||||
listen 80;
|
||||
server_name room.local.ar;
|
||||
# ... same locations but without sub_filter in / block
|
||||
}
|
||||
```
|
||||
|
||||
4. Reload nginx: `sudo nginx -t && sudo systemctl reload nginx`
|
||||
|
||||
**Pros**: Multiple rooms on port 80 via different hostnames
|
||||
**Cons**: Requires system nginx, manual config updates
|
||||
|
||||
## Port Allocation
|
||||
|
||||
Each room should use unique ports to allow concurrent operation:
|
||||
|
||||
| Room | Soleprint | Frontend | Backend |
|
||||
|--------|-----------|----------|---------|
|
||||
| amar | 12000 | 3000 | 8001 |
|
||||
| dlt | 12010 | 3010 | - |
|
||||
| sample | 12020 | 3020 | 8020 |
|
||||
|
||||
## Sidebar Assets
|
||||
|
||||
The sidebar consists of two files served by soleprint:
|
||||
|
||||
- `/sidebar.css` - Styles for the sidebar (dark theme, positioning)
|
||||
- `/sidebar.js` - Self-contained JS that fetches config and renders sidebar
|
||||
|
||||
Source location: `soleprint/station/tools/sbwrapper/`
|
||||
|
||||
## Sidebar Config API
|
||||
|
||||
The sidebar JS fetches configuration from `/spr/api/sidebar/config`:
|
||||
|
||||
```json
|
||||
{
|
||||
"room": "amar",
|
||||
"soleprint_base": "/spr",
|
||||
"auth_enabled": true,
|
||||
"tools": {
|
||||
"artery": "/spr/artery",
|
||||
"atlas": "/spr/atlas",
|
||||
"station": "/spr/station"
|
||||
},
|
||||
"auth": {
|
||||
"login_url": "/spr/artery/google/oauth/login",
|
||||
"logout_url": "/spr/artery/google/oauth/logout"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Sidebar not appearing
|
||||
|
||||
1. Check if soleprint is running: `curl http://room.spr.local.ar/spr/sidebar.js`
|
||||
2. Check browser console for `[Soleprint]` messages
|
||||
3. Verify nginx has `Accept-Encoding ""` set (required for sub_filter)
|
||||
4. Hard refresh (Ctrl+Shift+R) to clear cached HTML
|
||||
|
||||
### Wrong room config showing
|
||||
|
||||
Each room needs its own docker network (`room_network`) to isolate services. Check `NETWORK_NAME` in `.env` files and ensure containers are on correct networks.
|
||||
|
||||
### sub_filter not working
|
||||
|
||||
- Ensure `proxy_set_header Accept-Encoding ""` is set
|
||||
- Check that response is `text/html` (sub_filter_types)
|
||||
- Streaming SSR may not have `</body>`, use `</head>` injection instead
|
||||
@@ -1,115 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Graph Viewer - Soleprint</title>
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
<body class="graph-viewer">
|
||||
<header class="graph-header">
|
||||
<a href="index.html" class="back-link">← Back</a>
|
||||
<div class="nav-controls">
|
||||
<button onclick="navigate(-1)" id="btn-prev" title="Previous">◀</button>
|
||||
<span id="nav-position">1 / 4</span>
|
||||
<button onclick="navigate(1)" id="btn-next" title="Next">▶</button>
|
||||
</div>
|
||||
<h1 id="graph-title">Loading...</h1>
|
||||
<div class="graph-controls">
|
||||
<button onclick="setMode('fit')">Fit</button>
|
||||
<button onclick="setMode('fit-width')">Width</button>
|
||||
<button onclick="setMode('fit-height')">Height</button>
|
||||
<button onclick="setMode('actual-size')">100%</button>
|
||||
<button onclick="downloadSvg()">↓ SVG</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="graph-container" id="graph-container">
|
||||
<img id="graph-img" src="" alt="Graph" />
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const graphOrder = [
|
||||
"01-system-overview",
|
||||
"02-artery-hierarchy",
|
||||
"03-build-flow",
|
||||
"04-room-config",
|
||||
];
|
||||
|
||||
const graphs = {
|
||||
"01-system-overview": {
|
||||
title: "System Overview",
|
||||
file: "01-system-overview.svg",
|
||||
},
|
||||
"02-artery-hierarchy": {
|
||||
title: "Artery Hierarchy",
|
||||
file: "02-artery-hierarchy.svg",
|
||||
},
|
||||
"03-build-flow": {
|
||||
title: "Build Flow",
|
||||
file: "03-build-flow.svg",
|
||||
},
|
||||
"04-room-config": {
|
||||
title: "Room Configuration",
|
||||
file: "04-room-config.svg",
|
||||
},
|
||||
};
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
let graphKey = params.get("g") || "01-system-overview";
|
||||
let currentIndex = graphOrder.indexOf(graphKey);
|
||||
if (currentIndex === -1) currentIndex = 0;
|
||||
|
||||
function loadGraph(key) {
|
||||
const graph = graphs[key];
|
||||
document.getElementById("graph-title").textContent = graph.title;
|
||||
document.getElementById("graph-img").src = graph.file;
|
||||
document.title = graph.title + " - Soleprint";
|
||||
history.replaceState(null, "", "?g=" + key);
|
||||
graphKey = key;
|
||||
updateNavHints();
|
||||
}
|
||||
|
||||
function updateNavHints() {
|
||||
const idx = graphOrder.indexOf(graphKey);
|
||||
const prevBtn = document.getElementById("btn-prev");
|
||||
const nextBtn = document.getElementById("btn-next");
|
||||
prevBtn.disabled = idx === 0;
|
||||
nextBtn.disabled = idx === graphOrder.length - 1;
|
||||
document.getElementById("nav-position").textContent =
|
||||
idx + 1 + " / " + graphOrder.length;
|
||||
}
|
||||
|
||||
function navigate(direction) {
|
||||
const idx = graphOrder.indexOf(graphKey);
|
||||
const newIdx = idx + direction;
|
||||
if (newIdx >= 0 && newIdx < graphOrder.length) {
|
||||
currentIndex = newIdx;
|
||||
loadGraph(graphOrder[newIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
function setMode(mode) {
|
||||
const container = document.getElementById("graph-container");
|
||||
container.className = "graph-container " + mode;
|
||||
}
|
||||
|
||||
function downloadSvg() {
|
||||
const graph = graphs[graphKey];
|
||||
const link = document.createElement("a");
|
||||
link.href = graph.file;
|
||||
link.download = graph.file;
|
||||
link.click();
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "ArrowLeft") navigate(-1);
|
||||
else if (e.key === "ArrowRight") navigate(1);
|
||||
else if (e.key === "Escape") window.location.href = "index.html";
|
||||
});
|
||||
|
||||
loadGraph(graphOrder[currentIndex]);
|
||||
setMode("fit");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,259 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Soleprint - Architecture</title>
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Soleprint</h1>
|
||||
<p class="subtitle">
|
||||
Cada paso deja huella / Each step leaves a mark
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<!-- What it solves -->
|
||||
<section class="findings-section">
|
||||
<h2>What Soleprint Solves</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Freelance Work Standardization</h3>
|
||||
<p>
|
||||
Consistent framework across projects. Build once,
|
||||
reuse everywhere.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Missing Infrastructure</h3>
|
||||
<p>
|
||||
Mock systems you can't access yet - DB designs in
|
||||
progress, Kubernetes not ready, APIs being built.
|
||||
Test locally with shunts.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Reliable Testing</h3>
|
||||
<p>
|
||||
BDD -> Gherkin -> Tests. Explore behavior first,
|
||||
then generate tests.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- System Overview -->
|
||||
<section class="graph-section" id="overview">
|
||||
<div class="graph-header-row">
|
||||
<h2>System Overview</h2>
|
||||
<a href="graph.html?g=01-system-overview" class="view-btn"
|
||||
>View Full</a
|
||||
>
|
||||
</div>
|
||||
<a href="graph.html?g=01-system-overview" class="graph-preview">
|
||||
<img src="01-system-overview.svg" alt="System Overview" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>The four systems that make up Soleprint.</p>
|
||||
<h4>Systems</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Soleprint</strong>: Core coordinator hub
|
||||
(port 12000)
|
||||
</li>
|
||||
<li>
|
||||
<strong>Artery</strong>: Connectors to external
|
||||
services - "Todo lo vital"
|
||||
</li>
|
||||
<li>
|
||||
<strong>Atlas</strong>: Actionable documentation -
|
||||
"Documentacion accionable"
|
||||
</li>
|
||||
<li>
|
||||
<strong>Station</strong>: Tools and monitors -
|
||||
"Centro de control"
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Artery Hierarchy -->
|
||||
<section class="graph-section" id="artery">
|
||||
<div class="graph-header-row">
|
||||
<h2>Artery Hierarchy</h2>
|
||||
<a href="graph.html?g=02-artery-hierarchy" class="view-btn"
|
||||
>View Full</a
|
||||
>
|
||||
</div>
|
||||
<a
|
||||
href="graph.html?g=02-artery-hierarchy"
|
||||
class="graph-preview"
|
||||
>
|
||||
<img src="02-artery-hierarchy.svg" alt="Artery Hierarchy" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>How connectors evolve from simple to complex.</p>
|
||||
<h4>Connector Types</h4>
|
||||
<table class="details-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Vein</td>
|
||||
<td>Stateless API connector</td>
|
||||
<td>Jira, Slack, Google</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Shunt</td>
|
||||
<td>Fake connector for testing</td>
|
||||
<td>MercadoPago mock</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pulse</td>
|
||||
<td>Vein + Room + Depot</td>
|
||||
<td>Jira for AMAR project</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Plexus</td>
|
||||
<td>Full app (backend + frontend + DB)</td>
|
||||
<td>WhatsApp with chat UI</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Build Flow -->
|
||||
<section class="graph-section" id="build">
|
||||
<div class="graph-header-row">
|
||||
<h2>Build Flow</h2>
|
||||
<a href="graph.html?g=03-build-flow" class="view-btn"
|
||||
>View Full</a
|
||||
>
|
||||
</div>
|
||||
<a href="graph.html?g=03-build-flow" class="graph-preview">
|
||||
<img src="03-build-flow.svg" alt="Build Flow" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>How source is built into runnable instances.</p>
|
||||
<h4>Commands</h4>
|
||||
<table class="details-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Output</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>python build.py</code></td>
|
||||
<td>gen/standalone/</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>python build.py --cfg amar</code>
|
||||
</td>
|
||||
<td>gen/amar/</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>python build.py --all</code></td>
|
||||
<td>both</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Room Config -->
|
||||
<section class="graph-section" id="room">
|
||||
<div class="graph-header-row">
|
||||
<h2>Room Configuration</h2>
|
||||
<a href="graph.html?g=04-room-config" class="view-btn"
|
||||
>View Full</a
|
||||
>
|
||||
</div>
|
||||
<a href="graph.html?g=04-room-config" class="graph-preview">
|
||||
<img src="04-room-config.svg" alt="Room Configuration" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>How rooms are configured in cfg/.</p>
|
||||
<h4>Room Structure</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>config.json</strong>: Framework branding,
|
||||
terminology
|
||||
</li>
|
||||
<li>
|
||||
<strong>data/</strong>: veins.json, shunts.json,
|
||||
depots.json
|
||||
</li>
|
||||
<li>
|
||||
<strong>soleprint/</strong>: Docker config for this
|
||||
room
|
||||
</li>
|
||||
<li>
|
||||
<strong
|
||||
>databrowse/, tester/, monitors/,
|
||||
models/</strong
|
||||
>: Room-specific extensions
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tech Stack -->
|
||||
<section class="tech-section">
|
||||
<h2>Technology Stack</h2>
|
||||
<div class="tech-grid">
|
||||
<div class="tech-column">
|
||||
<h3>Core</h3>
|
||||
<ul>
|
||||
<li>Python 3.11+</li>
|
||||
<li>FastAPI</li>
|
||||
<li>Jinja2</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>Tools</h3>
|
||||
<ul>
|
||||
<li>modelgen</li>
|
||||
<li>tester (Playwright)</li>
|
||||
<li>datagen</li>
|
||||
<li>databrowse</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>Veins</h3>
|
||||
<ul>
|
||||
<li>Jira</li>
|
||||
<li>Slack</li>
|
||||
<li>Google (OAuth)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>Infrastructure</h3>
|
||||
<ul>
|
||||
<li>Docker</li>
|
||||
<li>Woodpecker CI</li>
|
||||
<li>Nginx</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>Soleprint - Development Workflow Platform</p>
|
||||
<p class="date">
|
||||
Generated: <time datetime="2025-01">January 2025</time>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,191 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sidebar Injection - Soleprint</title>
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
<style>
|
||||
pre {
|
||||
background: #1a1a1a;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
code {
|
||||
font-family: monospace;
|
||||
background: #2a2a2a;
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #3f3f3f;
|
||||
padding: 0.5rem;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
</style>
|
||||
<script src="../lang-toggle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="lang-toggle"></div>
|
||||
<h1>Sidebar Injection</h1>
|
||||
<p class="subtitle">
|
||||
<span class="lang-en">How managed room sidebar works</span>
|
||||
<span class="lang-es">Como funciona el sidebar del managed room</span>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="findings-section">
|
||||
<h2>Overview</h2>
|
||||
<p class="lang-en">The soleprint sidebar is injected into managed app pages using a hybrid nginx + JavaScript approach. This allows any frontend framework (React, Next.js, static HTML) to receive the sidebar without code modifications.</p>
|
||||
<p class="lang-es">El sidebar de soleprint se inyecta en las paginas de apps manejadas usando un enfoque hibrido nginx + JavaScript. Esto permite que cualquier framework frontend (React, Next.js, HTML estatico) reciba el sidebar sin modificaciones de codigo.</p>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">How It Works</span>
|
||||
<span class="lang-es">Como Funciona</span>
|
||||
</h2>
|
||||
<pre>
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Browser Request │
|
||||
│ http://room.spr.local.ar/ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Nginx │
|
||||
│ │
|
||||
│ 1. Routes /spr/* → soleprint:PORT (sidebar assets + API) │
|
||||
│ 2. Routes /* → frontend:PORT (app pages) │
|
||||
│ 3. Injects CSS+JS into HTML responses via sub_filter │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Browser Renders │
|
||||
│ │
|
||||
│ 1. Page loads with injected CSS (sidebar styles ready) │
|
||||
│ 2. sidebar.js executes (deferred, after DOM ready) │
|
||||
│ 3. JS fetches /spr/api/sidebar/config │
|
||||
│ 4. JS creates sidebar DOM elements and injects into page │
|
||||
│ 5. Sidebar appears on left side, pushes content with margin │
|
||||
└─────────────────────────────────────────────────────────────────┘</pre>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Key Design Decisions</span>
|
||||
<span class="lang-es">Decisiones de Diseno Clave</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3><span class="lang-en">Why nginx sub_filter?</span><span class="lang-es">Por que nginx sub_filter?</span></h3>
|
||||
<p class="lang-en"><strong>Framework agnostic</strong>: Works with any frontend. No app changes needed. Easy to disable.</p>
|
||||
<p class="lang-es"><strong>Agnostico de framework</strong>: Funciona con cualquier frontend. Sin cambios en la app. Facil de deshabilitar.</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3><span class="lang-en">Why inject into </head>?</span><span class="lang-es">Por que inyectar en </head>?</span></h3>
|
||||
<p class="lang-en">Next.js and streaming SSR may not include </body> in initial response. </head> is always present.</p>
|
||||
<p class="lang-es">Next.js y SSR streaming pueden no incluir </body> en la respuesta inicial. </head> siempre esta presente.</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3><span class="lang-en">Why JS instead of iframe?</span><span class="lang-es">Por que JS en vez de iframe?</span></h3>
|
||||
<p class="lang-en">No isolation issues, better UX (no double scrollbars), simpler CSS with margin-left.</p>
|
||||
<p class="lang-es">Sin problemas de aislamiento, mejor UX (sin doble scrollbar), CSS mas simple con margin-left.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Nginx Configuration</span>
|
||||
<span class="lang-es">Configuracion de Nginx</span>
|
||||
</h2>
|
||||
<p class="lang-en">The nginx config injects CSS+JS into HTML responses:</p>
|
||||
<p class="lang-es">La config de nginx inyecta CSS+JS en las respuestas HTML:</p>
|
||||
<pre><code>location / {
|
||||
proxy_pass http://frontend:PORT;
|
||||
proxy_set_header Accept-Encoding ""; # Required for sub_filter
|
||||
|
||||
# Inject sidebar
|
||||
sub_filter '</head>'
|
||||
'<link rel="stylesheet" href="/spr/sidebar.css">
|
||||
<script src="/spr/sidebar.js" defer></script></head>';
|
||||
sub_filter_once off;
|
||||
sub_filter_types text/html;
|
||||
}</code></pre>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Port Allocation</span>
|
||||
<span class="lang-es">Asignacion de Puertos</span>
|
||||
</h2>
|
||||
<p class="lang-en">Each room uses unique ports for concurrent operation:</p>
|
||||
<p class="lang-es">Cada room usa puertos unicos para operacion concurrente:</p>
|
||||
<table>
|
||||
<tr><th>Room</th><th>Soleprint</th><th>Frontend</th><th>Backend</th></tr>
|
||||
<tr><td>amar</td><td>12000</td><td>3000</td><td>8001</td></tr>
|
||||
<tr><td>dlt</td><td>12010</td><td>3010</td><td>-</td></tr>
|
||||
<tr><td>sample</td><td>12020</td><td>3020</td><td>8020</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Sidebar Config API</span>
|
||||
<span class="lang-es">API de Config del Sidebar</span>
|
||||
</h2>
|
||||
<p class="lang-en">The sidebar JS fetches configuration from <code>/spr/api/sidebar/config</code>:</p>
|
||||
<p class="lang-es">El JS del sidebar obtiene configuracion de <code>/spr/api/sidebar/config</code>:</p>
|
||||
<pre><code>{
|
||||
"room": "amar",
|
||||
"soleprint_base": "/spr",
|
||||
"auth_enabled": true,
|
||||
"tools": {
|
||||
"artery": "/spr/artery",
|
||||
"atlas": "/spr/atlas",
|
||||
"station": "/spr/station"
|
||||
}
|
||||
}</code></pre>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>Troubleshooting</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3><span class="lang-en">Sidebar not appearing</span><span class="lang-es">Sidebar no aparece</span></h3>
|
||||
<p class="lang-en">Check if soleprint is running. Verify nginx has <code>Accept-Encoding ""</code>. Hard refresh (Ctrl+Shift+R).</p>
|
||||
<p class="lang-es">Verificar que soleprint esta corriendo. Verificar que nginx tiene <code>Accept-Encoding ""</code>. Refresco forzado (Ctrl+Shift+R).</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3><span class="lang-en">sub_filter not working</span><span class="lang-es">sub_filter no funciona</span></h3>
|
||||
<p class="lang-en">Ensure <code>proxy_set_header Accept-Encoding ""</code> is set. Check response is <code>text/html</code>.</p>
|
||||
<p class="lang-es">Asegurar que <code>proxy_set_header Accept-Encoding ""</code> esta seteado. Verificar que la respuesta es <code>text/html</code>.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p><a href="../"><span class="lang-en">← Back to index</span><span class="lang-es">← Volver al indice</span></a></p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,351 +0,0 @@
|
||||
:root {
|
||||
--bg-primary: #0a0a0a;
|
||||
--bg-secondary: #141414;
|
||||
--bg-card: #1a1a1a;
|
||||
--text-primary: #eee;
|
||||
--text-secondary: #a0a0a0;
|
||||
--accent: #e94560;
|
||||
--accent-secondary: #533483;
|
||||
--border: #2a2a2a;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family:
|
||||
"Segoe UI",
|
||||
system-ui,
|
||||
-apple-system,
|
||||
sans-serif;
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
header {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--bg-secondary),
|
||||
var(--accent-secondary)
|
||||
);
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
border-bottom: 2px solid var(--accent);
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
header .subtitle {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
/* Graph sections */
|
||||
.graph-section {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.graph-header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.graph-header-row h2 {
|
||||
font-size: 1.25rem;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.view-btn {
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
font-size: 0.875rem;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.view-btn:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.graph-preview {
|
||||
display: block;
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
.graph-preview img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.graph-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.graph-details h4 {
|
||||
color: var(--text-primary);
|
||||
margin: 1rem 0 0.5rem;
|
||||
}
|
||||
|
||||
.graph-details ul {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.graph-details li {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
/* Tech section */
|
||||
.tech-section {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.tech-section h2 {
|
||||
color: var(--accent);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.tech-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.tech-column h3 {
|
||||
color: var(--text-primary);
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.tech-column ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.tech-column li {
|
||||
padding: 0.25rem 0;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* Findings */
|
||||
.findings-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.findings-section h2 {
|
||||
color: var(--accent);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.findings-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.finding-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 1.25rem;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.finding-card h3 {
|
||||
color: var(--accent);
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.finding-card ul {
|
||||
margin-left: 1rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.finding-card code {
|
||||
background: var(--bg-primary);
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 3px;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: var(--text-secondary);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
footer .date {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* Graph viewer page */
|
||||
body.graph-viewer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.graph-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: var(--bg-secondary);
|
||||
border-bottom: 1px solid var(--border);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-controls button {
|
||||
background: var(--bg-card);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-controls button:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
#nav-position {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.graph-header h1 {
|
||||
flex: 1;
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.graph-controls {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.graph-controls button {
|
||||
background: var(--bg-card);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.375rem 0.75rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.graph-controls button:hover {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.graph-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.graph-container.fit img {
|
||||
max-width: 100%;
|
||||
max-height: calc(100vh - 60px);
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.graph-container.fit-width img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.graph-container.fit-height img {
|
||||
height: calc(100vh - 60px);
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.graph-container.actual-size img {
|
||||
/* No constraints */
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.details-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.details-table th,
|
||||
.details-table td {
|
||||
padding: 0.5rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.details-table th {
|
||||
color: var(--text-primary);
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
.details-table td {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.details-table code {
|
||||
background: var(--bg-primary);
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.note {
|
||||
font-style: italic;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Artery - Soleprint</title>
|
||||
<link rel="stylesheet" href="../architecture/styles.css" />
|
||||
<style>
|
||||
.composition {
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #b91c1c;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.composition h3 {
|
||||
margin: 0 0 0.75rem 0;
|
||||
font-size: 1.1rem;
|
||||
color: #fca5a5;
|
||||
}
|
||||
.composition > p {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 0.9rem;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.components {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.component {
|
||||
background: #0a0a0a;
|
||||
border: 1px solid #3f3f3f;
|
||||
padding: 0.75rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.component h4 {
|
||||
margin: 0 0 0.25rem 0;
|
||||
font-size: 0.95rem;
|
||||
color: #fca5a5;
|
||||
}
|
||||
.component p {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.model-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
<script src="../lang-toggle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="lang-toggle"></div>
|
||||
<h1>Artery</h1>
|
||||
<p class="subtitle">Todo lo vital</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Model</span
|
||||
><span class="lang-es">Modelo</span>
|
||||
</h2>
|
||||
<div class="model-grid">
|
||||
<div class="composition">
|
||||
<h3>Pulse</h3>
|
||||
<p class="lang-en">
|
||||
Composed data flow: a vein configured for a room
|
||||
with storage
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Flujo de datos compuesto: vein configurado para un
|
||||
room con almacenamiento
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>Vein</h4>
|
||||
<p class="lang-en">API connector</p>
|
||||
<p class="lang-es">Conector API</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Room</h4>
|
||||
<p class="lang-en">Config/env</p>
|
||||
<p class="lang-es">Config/entorno</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Depot</h4>
|
||||
<p class="lang-en">Data storage</p>
|
||||
<p class="lang-es">Almacenamiento</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="composition">
|
||||
<h3>Shunt</h3>
|
||||
<p class="lang-en">
|
||||
Mock connector for testing - same interface, fake
|
||||
data
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Conector mock para testing - misma interfaz, datos
|
||||
falsos
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>Vein Interface</h4>
|
||||
<p class="lang-en">Same API shape</p>
|
||||
<p class="lang-es">Misma forma de API</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Mock Data</h4>
|
||||
<p class="lang-en">Fake responses</p>
|
||||
<p class="lang-es">Respuestas falsas</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="composition">
|
||||
<h3>Plexus</h3>
|
||||
<p class="lang-en">
|
||||
Full application when you need more than data flow
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Aplicacion completa cuando necesitas mas que flujo
|
||||
de datos
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>Backend</h4>
|
||||
<p>FastAPI server</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Frontend</h4>
|
||||
<p>Web UI</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Infra</h4>
|
||||
<p class="lang-en">DB, queues, etc</p>
|
||||
<p class="lang-es">DB, colas, etc</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Architecture</span
|
||||
><span class="lang-es">Arquitectura</span>
|
||||
</h2>
|
||||
<img
|
||||
src="../architecture/02-artery-hierarchy.svg"
|
||||
alt="Artery Hierarchy"
|
||||
style="
|
||||
max-width: 100%;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Components</span
|
||||
><span class="lang-es">Componentes</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Vein</h3>
|
||||
<p class="lang-en">
|
||||
Stateless API connector. Connects to external
|
||||
services like Google Sheets, Jira, Slack. Pure data
|
||||
flow - no state, no storage.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Conector API sin estado. Conecta a servicios
|
||||
externos como Google Sheets, Jira, Slack. Flujo de
|
||||
datos puro.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Shunt</h3>
|
||||
<p class="lang-en">
|
||||
Mock connector for testing. Same interface as a vein
|
||||
but returns fake data.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Conector mock para testing. Misma interfaz que un
|
||||
vein pero devuelve datos falsos.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Pulse</h3>
|
||||
<p class="lang-en">
|
||||
Composed data flow. Formula:
|
||||
<strong>Vein + Room + Depot</strong>.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Flujo de datos compuesto. Formula:
|
||||
<strong>Vein + Room + Depot</strong>.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Plexus</h3>
|
||||
<p class="lang-en">
|
||||
Full application with backend, frontend, and
|
||||
infrastructure.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Aplicacion completa con backend, frontend e
|
||||
infraestructura.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Shared Components</span
|
||||
><span class="lang-es">Componentes Compartidos</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Room</h3>
|
||||
<p class="lang-en">
|
||||
Runtime environment configuration. Each room is an
|
||||
isolated instance with its own config and
|
||||
credentials.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Configuracion del entorno. Cada room es una
|
||||
instancia aislada con su propia config y
|
||||
credenciales.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Depot</h3>
|
||||
<p class="lang-en">
|
||||
Data storage / provisions. JSON files, configs,
|
||||
cached responses.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Almacenamiento de datos. Archivos JSON, configs,
|
||||
respuestas cacheadas.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Available Veins</span
|
||||
><span class="lang-es">Veins Disponibles</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<a
|
||||
href="../veins/index.html"
|
||||
class="finding-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>Google</h3>
|
||||
<p class="lang-en">
|
||||
Google Sheets API. OAuth authentication, read/write
|
||||
spreadsheets.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Google Sheets API. Autenticacion OAuth,
|
||||
leer/escribir hojas de calculo.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="../veins/index.html"
|
||||
class="finding-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>Jira</h3>
|
||||
<p class="lang-en">
|
||||
Jira Cloud API. Query issues, projects, sprints.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Jira Cloud API. Consultar issues, proyectos,
|
||||
sprints.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="../veins/index.html"
|
||||
class="finding-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>Slack</h3>
|
||||
<p class="lang-en">
|
||||
Slack API. Channels, messages, users.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Slack API. Canales, mensajes, usuarios.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="../"
|
||||
><span class="lang-en">← Back to index</span
|
||||
><span class="lang-es">← Volver al indice</span></a
|
||||
>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,209 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Atlas - Soleprint</title>
|
||||
<link rel="stylesheet" href="../architecture/styles.css" />
|
||||
<style>
|
||||
.composition {
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #15803d;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.composition h3 {
|
||||
margin: 0 0 0.75rem 0;
|
||||
font-size: 1.1rem;
|
||||
color: #86efac;
|
||||
}
|
||||
.composition > p {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 0.9rem;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.components {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.component {
|
||||
background: #0a0a0a;
|
||||
border: 1px solid #3f3f3f;
|
||||
padding: 0.75rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.component h4 {
|
||||
margin: 0 0 0.25rem 0;
|
||||
font-size: 0.95rem;
|
||||
color: #86efac;
|
||||
}
|
||||
.component p {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.model-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
<script src="../lang-toggle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="lang-toggle"></div>
|
||||
<h1>Atlas</h1>
|
||||
<p class="subtitle">
|
||||
<span class="lang-en">Actionable Documentation</span
|
||||
><span class="lang-es">Documentacion Accionable</span>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Model</span
|
||||
><span class="lang-es">Modelo</span>
|
||||
</h2>
|
||||
<div class="model-grid">
|
||||
<div class="composition">
|
||||
<h3>Plain Book</h3>
|
||||
<p class="lang-en">
|
||||
Static documentation with an index page
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Documentacion estatica con una pagina indice
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>index.html</h4>
|
||||
<p class="lang-en">Entry point</p>
|
||||
<p class="lang-es">Punto de entrada</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Depot</h4>
|
||||
<p class="lang-en">Static content</p>
|
||||
<p class="lang-es">Contenido estatico</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="composition">
|
||||
<h3>Templated Book</h3>
|
||||
<p class="lang-en">
|
||||
Dynamic docs from template + data elements
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Docs dinamicos desde template + elementos de datos
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>Template</h4>
|
||||
<p class="lang-en">Jinja2 pattern</p>
|
||||
<p class="lang-es">Patron Jinja2</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Depot</h4>
|
||||
<p class="lang-en">Data elements</p>
|
||||
<p class="lang-es">Elementos de datos</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Architecture</span
|
||||
><span class="lang-es">Arquitectura</span>
|
||||
</h2>
|
||||
<img
|
||||
src="../architecture/01-system-overview.svg"
|
||||
alt="System Overview"
|
||||
style="
|
||||
max-width: 100%;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Components</span
|
||||
><span class="lang-es">Componentes</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Book</h3>
|
||||
<p class="lang-en">
|
||||
Collection of related documentation. Can be plain
|
||||
(static HTML) or templated (template + depot
|
||||
elements).
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Coleccion de documentacion relacionada. Puede ser
|
||||
plain (HTML estatico) o templated (template +
|
||||
elementos de depot).
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Template</h3>
|
||||
<p class="lang-en">
|
||||
Jinja2 templates that generate documentation. Define
|
||||
the structure once, fill with data from depot.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Templates Jinja2 que generan documentacion. Definen
|
||||
la estructura una vez, llenan con datos del depot.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Shared Components</span
|
||||
><span class="lang-es">Componentes Compartidos</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Room</h3>
|
||||
<p class="lang-en">
|
||||
Runtime environment configuration. Each room can
|
||||
have its own atlas with project-specific books.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Configuracion del entorno. Cada room puede tener su
|
||||
propio atlas con books especificos del proyecto.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Depot</h3>
|
||||
<p class="lang-en">
|
||||
Data storage. For plain books: static files. For
|
||||
templated books: elements that fill the template.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Almacenamiento de datos. Para plain books: archivos
|
||||
estaticos. Para templated books: elementos que
|
||||
llenan el template.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="../"
|
||||
><span class="lang-en">← Back to index</span
|
||||
><span class="lang-es">← Volver al indice</span></a
|
||||
>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
55
docs/data/en/artery-google.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Google Vein
|
||||
|
||||
Status: **building**
|
||||
|
||||
Connects soleprint to Google services. OAuth2 flow is implemented. Sheets read access works. Calendar and Drive are next.
|
||||
|
||||
---
|
||||
|
||||
## What Works
|
||||
|
||||
**OAuth2 authentication** -- full flow with authorization URL generation, code exchange, token refresh, and user identity extraction. Supports both identity (OpenID Connect) and API access scopes.
|
||||
|
||||
**Google Sheets** -- read-only access to spreadsheet data.
|
||||
|
||||
## Configuration
|
||||
|
||||
Create a `.env` file in the vein directory:
|
||||
|
||||
```env
|
||||
GOOGLE_CLIENT_ID=your-client-id
|
||||
GOOGLE_CLIENT_SECRET=your-client-secret
|
||||
GOOGLE_REDIRECT_URI=http://localhost:12000/artery/google/oauth/callback
|
||||
API_PORT=8003
|
||||
```
|
||||
|
||||
You need a Google Cloud project with OAuth consent screen configured and credentials created.
|
||||
|
||||
## OAuth Scopes
|
||||
|
||||
Identity scopes (default):
|
||||
|
||||
- `openid`
|
||||
- `userinfo.email`
|
||||
- `userinfo.profile`
|
||||
|
||||
API scopes (added when needed):
|
||||
|
||||
- `spreadsheets.readonly`
|
||||
- `drive.readonly`
|
||||
|
||||
## What's Coming
|
||||
|
||||
- Calendar integration
|
||||
- Drive file browsing and download
|
||||
- Full Sheets write support
|
||||
|
||||
Configuration details will be added as these integrations mature.
|
||||
|
||||
## Running Standalone
|
||||
|
||||
```bash
|
||||
cd soleprint/artery/veins/google
|
||||
python run.py
|
||||
# Runs on port 8003
|
||||
```
|
||||
77
docs/data/en/artery-ia.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# IA Vein
|
||||
|
||||
Status: **live**
|
||||
|
||||
Connects soleprint to AI/LLM providers. Uses an OpenAI-compatible API interface, so it works with OpenAI, Anthropic (via proxy), local models, or any compatible endpoint.
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
- Generic chat completion endpoint
|
||||
- Health check against the configured provider
|
||||
- Use-case-specific routers mounted as sub-routes
|
||||
- JSON extraction from AI responses
|
||||
|
||||
## Configuration
|
||||
|
||||
Create a `.env` file in the vein directory:
|
||||
|
||||
```env
|
||||
AI_API_URL=https://api.openai.com/v1
|
||||
AI_API_KEY=your-api-key
|
||||
AI_MODEL=gpt-4o
|
||||
API_PORT=8005
|
||||
```
|
||||
|
||||
`AI_API_URL` defaults to OpenAI. Point it at any OpenAI-compatible endpoint.
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/ia/health` | Test API connection, returns provider and model info |
|
||||
| POST | `/ia/chat` | Generic chat completion |
|
||||
| | `/ia/practice/*` | Practice use-case routes |
|
||||
|
||||
## Authentication
|
||||
|
||||
API key resolves in order:
|
||||
|
||||
1. `X-AI-Token` HTTP header
|
||||
2. `.env` file value
|
||||
|
||||
This lets soleprint tools pass their own keys per-request.
|
||||
|
||||
## Chat Request
|
||||
|
||||
```json
|
||||
{
|
||||
"messages": [
|
||||
{"role": "system", "content": "You are helpful."},
|
||||
{"role": "user", "content": "Hello"}
|
||||
],
|
||||
"temperature": 0.7,
|
||||
"max_tokens": 1024
|
||||
}
|
||||
```
|
||||
|
||||
The response includes `content` (raw text) and `parsed` (first valid JSON object extracted from the response, if any).
|
||||
|
||||
## Use Cases
|
||||
|
||||
The IA vein supports use-case-specific routers mounted under `/ia/{usecase}/`. Each use case has its own prompts, models, and routes.
|
||||
|
||||
Currently implemented:
|
||||
|
||||
- **Practice** -- AI-powered practice sessions with structured prompts and formatted output
|
||||
|
||||
## Running Standalone
|
||||
|
||||
```bash
|
||||
cd soleprint/artery/veins/ia
|
||||
python run.py
|
||||
# Runs on port 8005
|
||||
```
|
||||
|
||||
Or through soleprint, where it is mounted under `/artery/ia/`.
|
||||
71
docs/data/en/artery-jira.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Jira Vein
|
||||
|
||||
Status: **live**
|
||||
|
||||
Connects soleprint to Jira Cloud. Fetches tickets, sprints, backlogs, and epics. Supports text and JSON output formats.
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
- Query your assigned tickets, project backlogs, and current sprints
|
||||
- Fetch full ticket details with comments, attachments, and child work items
|
||||
- Process entire epics: fetch the epic and all children, save to local storage
|
||||
- Search with raw JQL
|
||||
- Stream attachment content directly from Jira
|
||||
|
||||
## Configuration
|
||||
|
||||
Create a `.env` file in the vein directory or set environment variables:
|
||||
|
||||
```env
|
||||
JIRA_URL=https://your-org.atlassian.net
|
||||
JIRA_EMAIL=you@example.com
|
||||
JIRA_API_TOKEN=your-api-token
|
||||
API_PORT=8001
|
||||
```
|
||||
|
||||
`JIRA_EMAIL` and `JIRA_API_TOKEN` are optional in config. They can be provided per-request via HTTP headers instead, allowing one vein instance to serve multiple users.
|
||||
|
||||
Generate an API token at [id.atlassian.net/manage-profile/security/api-tokens](https://id.atlassian.net/manage-profile/security/api-tokens).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/health` | Test connection, returns authenticated user |
|
||||
| GET | `/mine` | Your assigned open tickets |
|
||||
| GET | `/backlog?project=KEY` | Project backlog |
|
||||
| GET | `/sprint?project=KEY` | Current sprint tickets |
|
||||
| GET | `/ticket/{key}` | Full ticket detail with comments and children |
|
||||
| POST | `/search` | Raw JQL query |
|
||||
| POST | `/epic/{key}/process` | Fetch entire epic tree, save to files (streaming) |
|
||||
| GET | `/epic/{key}/status` | Check if epic has been processed |
|
||||
| GET | `/attachment/{id}` | Stream attachment content |
|
||||
|
||||
All list endpoints support `page`, `page_size`, and `text=true` for plain-text output.
|
||||
|
||||
## Authentication
|
||||
|
||||
Credentials resolve in order:
|
||||
|
||||
1. HTTP headers (`X-Jira-Email`, `X-Jira-Token`)
|
||||
2. `.env` file values
|
||||
|
||||
## Text Mode
|
||||
|
||||
Pass `?text=true` to any query endpoint. Returns formatted plain text instead of JSON. Useful for piping into other tools or AI prompts.
|
||||
|
||||
## Epic Processing
|
||||
|
||||
The `/epic/{key}/process` endpoint streams progress as NDJSON. It fetches the epic, then each child ticket with a short delay between requests. All tickets are saved as JSON files to `artery/larder/jira_epics/{key}/`.
|
||||
|
||||
## Running Standalone
|
||||
|
||||
```bash
|
||||
cd soleprint/artery/veins/jira
|
||||
python run.py
|
||||
# Runs on port 8001
|
||||
```
|
||||
|
||||
Or through soleprint, where it is mounted under `/artery/jira/`.
|
||||
94
docs/data/en/artery-shunts.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Shunt Pattern
|
||||
|
||||
Shunts are fake connectors for testing. They mirror real API structures but return configurable mock data. No external service needed.
|
||||
|
||||
---
|
||||
|
||||
## Why Shunts
|
||||
|
||||
You need to test payment flows without charging real cards. You need to develop against an API that requires VPN access. You need predictable responses for BDD tests. Shunts solve all of these.
|
||||
|
||||
A shunt runs as a FastAPI app, same as a vein. Your code talks to it the same way it would talk to the real service. Swap the URL and you're testing against production.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
shunts/
|
||||
└── {name}/
|
||||
├── __init__.py
|
||||
├── main.py # FastAPI app
|
||||
├── run.py # Standalone runner
|
||||
├── core/
|
||||
│ └── config.py # Mock behavior settings
|
||||
├── api/
|
||||
│ └── routes.py # Mock endpoints
|
||||
└── templates/ # Optional config UI
|
||||
```
|
||||
|
||||
## Creating a Shunt
|
||||
|
||||
Start from the example template:
|
||||
|
||||
```bash
|
||||
cp -r soleprint/artery/shunts/example soleprint/artery/shunts/yourservice
|
||||
```
|
||||
|
||||
The example shunt provides:
|
||||
|
||||
- Health check endpoint
|
||||
- Config UI at root path
|
||||
- Catch-all GET/POST handlers that return responses from a `responses.json` file
|
||||
- `SHUNT_DEPOT` environment variable for external response storage
|
||||
|
||||
Edit `responses.json` to define your fake responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"GET /users": [{"id": 1, "name": "Test User"}],
|
||||
"POST /orders": {"id": 999, "status": "created"}
|
||||
}
|
||||
```
|
||||
|
||||
For more complex behavior, replace the catch-all handlers with specific route implementations.
|
||||
|
||||
## MercadoPago Shunt
|
||||
|
||||
The MercadoPago shunt is a full mock of the MercadoPago payment API. It demonstrates what a production-grade shunt looks like.
|
||||
|
||||
**What it mocks:**
|
||||
|
||||
- Checkout Pro preferences (`POST /v1/preferences`)
|
||||
- Payments (`POST /v1/payments`, `GET /v1/payments/{id}`)
|
||||
- Merchant orders (`GET /v1/merchant_orders/{id}`)
|
||||
- OAuth token exchange (`POST /oauth/token`)
|
||||
- Webhook simulation (`POST /mock/webhook`)
|
||||
|
||||
**Testing controls:**
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|----------|---------|
|
||||
| `POST /mock/config` | Set default payment status, error rate |
|
||||
| `GET /mock/reset` | Clear all mock data |
|
||||
| `GET /mock/stats` | Count of stored mock objects |
|
||||
|
||||
**Configurable behavior:**
|
||||
|
||||
- `default_payment_status` -- force all payments to approved, pending, or rejected
|
||||
- `error_rate` -- probability (0-1) of random 500 errors
|
||||
- `enable_random_delays` -- simulate real API latency
|
||||
- `min_delay_ms` / `max_delay_ms` -- delay range in milliseconds
|
||||
|
||||
Data is generated using `datagen`'s MercadoPago generator. Stored in memory. Reset between test runs with `/mock/reset`.
|
||||
|
||||
## Running a Shunt
|
||||
|
||||
```bash
|
||||
cd soleprint/artery/shunts/mercadopago
|
||||
python run.py
|
||||
```
|
||||
|
||||
Or configure it in your room's shunt registry so soleprint manages it.
|
||||
|
||||
## Room-Specific Shunts
|
||||
|
||||
Rooms can define their own shunts under `cfg/{room}/artery/shunts/`. These are merged into the build output alongside the core shunts.
|
||||
33
docs/data/en/artery-slack.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Slack Vein
|
||||
|
||||
Status: **building**
|
||||
|
||||
Will connect soleprint to Slack for channel messaging and notifications.
|
||||
|
||||
---
|
||||
|
||||
## What Exists
|
||||
|
||||
The vein structure is in place: config, client, auth, models, routes. Bot token and user token configuration is ready.
|
||||
|
||||
```env
|
||||
SLACK_BOT_TOKEN=xoxb-...
|
||||
SLACK_USER_TOKEN=xoxp-...
|
||||
API_PORT=8002
|
||||
```
|
||||
|
||||
## What's Coming
|
||||
|
||||
- Send messages to channels
|
||||
- Read channel history
|
||||
- Notification integration with other soleprint tools
|
||||
|
||||
Configuration details will be added as the integration matures.
|
||||
|
||||
## Running Standalone
|
||||
|
||||
```bash
|
||||
cd soleprint/artery/veins/slack
|
||||
python run.py
|
||||
# Runs on port 8002
|
||||
```
|
||||
110
docs/data/en/artery.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Artery
|
||||
|
||||
Artery is the connector system. It bridges soleprint to external services -- APIs, messaging platforms, payment processors, AI providers.
|
||||
|
||||
**Todo lo vital** -- everything vital flows through here.
|
||||
|
||||
---
|
||||
|
||||
## Hierarchy
|
||||
|
||||
Connectors scale from simple to full:
|
||||
|
||||
```
|
||||
Vein ──────► Pulse ──────► Plexus
|
||||
│ │ │
|
||||
│ │ └── Full app: backend + frontend + DB
|
||||
│ │
|
||||
│ └── Composed: Vein + Room + Depot
|
||||
│
|
||||
└── Stateless API connector
|
||||
|
||||
Shunt ─── Fake connector for testing
|
||||
```
|
||||
|
||||

|
||||
|
||||
**Vein** -- a stateless wrapper around an external API. Handles auth, exposes endpoints, runs standalone or through soleprint. Each vein follows the same structure: `core/` for the isolated client, `api/` for FastAPI routes, `models/` for data types.
|
||||
|
||||
**Shunt** -- a mock vein. Returns configurable fake responses so you can test without hitting real APIs. Shunts mirror real API structures but store everything in memory.
|
||||
|
||||
**Pulse** -- a vein composed with a room and a depot. Adds persistent storage and room-specific configuration on top of a raw vein.
|
||||
|
||||
**Plexus** -- a full application. Backend, frontend, database. The highest level of the hierarchy.
|
||||
|
||||
## Veins
|
||||
|
||||
| Vein | Status | Description |
|
||||
|------|--------|-------------|
|
||||
| [Jira](artery-jira.md) | live | Issue tracker integration |
|
||||
| [Google](artery-google.md) | building | OAuth, Sheets, Calendar, Drive |
|
||||
| [Slack](artery-slack.md) | building | Channel messaging |
|
||||
| [IA](artery-ia.md) | live | AI/LLM connector |
|
||||
| Maps | planned | Location services |
|
||||
| WhatsApp | planned | Messaging |
|
||||
| GNUCash | planned | Accounting |
|
||||
| VPN | planned | Network access |
|
||||
|
||||
## Shunts
|
||||
|
||||
| Shunt | Status | Description |
|
||||
|-------|--------|-------------|
|
||||
| [MercadoPago](artery-shunts.md) | ready | Mock payment processing API |
|
||||
| [Example](artery-shunts.md) | ready | Template for creating new shunts |
|
||||
|
||||
See [Shunt Pattern](artery-shunts.md) for how shunts work and how to create one.
|
||||
|
||||
## Vein Structure
|
||||
|
||||
Every vein follows the same layout:
|
||||
|
||||
```
|
||||
veins/
|
||||
└── {name}/
|
||||
├── __init__.py
|
||||
├── main.py # FastAPI app entry point
|
||||
├── run.py # Standalone runner
|
||||
├── .env # Credentials (not committed)
|
||||
├── core/
|
||||
│ ├── config.py # Pydantic settings from .env
|
||||
│ ├── client.py # Isolated API client
|
||||
│ └── auth.py # Auth handling
|
||||
├── api/
|
||||
│ └── routes.py # FastAPI router
|
||||
└── models/
|
||||
└── ... # Data models, formatters
|
||||
```
|
||||
|
||||
The `core/` module is isolated. It can run without FastAPI. The `api/` module wraps it in HTTP routes.
|
||||
|
||||
## Base Class
|
||||
|
||||
All veins extend `BaseVein`:
|
||||
|
||||
```python
|
||||
class BaseVein(ABC):
|
||||
name: str # e.g., 'jira', 'slack'
|
||||
get_client(creds) -> client # Create API client
|
||||
health_check(creds) -> dict # Test connection
|
||||
create_router() -> APIRouter # HTTP routes
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Veins load credentials from `.env` files using Pydantic settings. Credentials can also be passed per-request via HTTP headers, so one vein instance can serve multiple users.
|
||||
|
||||
Vein configurations are registered in `veins.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "jira",
|
||||
"slug": "jira",
|
||||
"title": "Jira",
|
||||
"status": "live",
|
||||
"system": "artery"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
86
docs/data/en/atlas-books.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Atlas Books
|
||||
|
||||
A book is a documentation library served through Atlas. It lives in a directory under `books/` and is served at `/book/{slug}/`.
|
||||
|
||||
---
|
||||
|
||||
## Two Types
|
||||
|
||||
**Standalone book** -- static HTML files. No template, no depot. Atlas serves them directly. The book and its content are the same thing.
|
||||
|
||||
**Templated book** -- a template defines the structure, a depot (called a larder) provides the data. Atlas renders a landing page with links to the template definition and the data browser.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
### Standalone Book
|
||||
|
||||
```
|
||||
books/
|
||||
└── feature-flow/
|
||||
├── index-en.html # English version
|
||||
├── index-es.html # Spanish version
|
||||
└── CLAUDE.md # Dev notes
|
||||
```
|
||||
|
||||
Routes:
|
||||
- `/book/feature-flow/` -- language picker
|
||||
- `/book/feature-flow/en` -- English
|
||||
- `/book/feature-flow/es` -- Spanish
|
||||
|
||||
A standalone book is just HTML. Put it in the directory, register it in `books.json`, add a route in `main.py`.
|
||||
|
||||
### Templated Book
|
||||
|
||||
```
|
||||
books/
|
||||
└── feature-form-samples/
|
||||
├── template/ # Template definition
|
||||
│ └── plantilla-flujo.md
|
||||
├── feature-form/ # Larder (data)
|
||||
│ ├── .larder # Marker file
|
||||
│ ├── pet-owner/
|
||||
│ ├── veterinarian/
|
||||
│ └── backoffice/
|
||||
├── index.html # Larder browser
|
||||
└── detail.html # Detail renderer
|
||||
```
|
||||
|
||||
Routes:
|
||||
- `/book/feature-form-samples/` -- landing page (links to template + larder)
|
||||
- `/book/feature-form-samples/template/` -- template definition
|
||||
- `/book/feature-form-samples/larder/` -- data browser
|
||||
- `/book/feature-form-samples/larder/{user_type}/{file}` -- specific entry
|
||||
|
||||
The `.larder` marker identifies which subdirectory holds the data.
|
||||
|
||||
## The Feature Flow Example
|
||||
|
||||
Feature Flow is the standalone reference. It documents the BDD standardization pipeline -- how features go from idea to Gherkin to test. Two languages, no template, pure HTML.
|
||||
|
||||
## Registration
|
||||
|
||||
Books are registered in `books.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "feature-flow",
|
||||
"slug": "feature-flow",
|
||||
"title": "Feature Flow Pipeline",
|
||||
"status": "ready",
|
||||
"system": "atlas"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Adding a Room-Specific Book
|
||||
|
||||
1. Create the book directory in `cfg/<room>/atlas/books/{slug}/`
|
||||
2. Add the HTML files
|
||||
3. Register it in the room's `books.json` (in `cfg/<room>/data/`)
|
||||
4. Add routes in main.py if it needs custom handling
|
||||
5. Build: `python build.py --cfg <room>`
|
||||
|
||||
The build merges room books into the output alongside core books. Room books can also override core books by using the same slug.
|
||||
75
docs/data/en/atlas-templates.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Atlas Templates
|
||||
|
||||
A template is a documentation pattern. It defines the structure that content must follow. Templates turn unstructured knowledge into consistent, browsable documentation.
|
||||
|
||||
---
|
||||
|
||||
## How Templates Work
|
||||
|
||||
A template defines fields, layout, and validation rules. Content that follows the template gets rendered through Atlas with consistent formatting and navigation.
|
||||
|
||||
Templates live in `soleprint/atlas/templates/` (core) or inside a book's `template/` subdirectory.
|
||||
|
||||
Data templates -- the schema files that define structure -- live in `cfg/<room>/data/template/`.
|
||||
|
||||
## The Feature Form Example
|
||||
|
||||
The feature form template captures user flows in a structured format:
|
||||
|
||||
| Field | Purpose |
|
||||
|-------|---------|
|
||||
| User Type | Who performs this flow |
|
||||
| Entry Point | Where the flow starts |
|
||||
| User Goal | One-sentence objective |
|
||||
| Steps | Numbered sequence of actions |
|
||||
| Expected Result | What success looks like |
|
||||
| Common Problems | Known failure modes |
|
||||
| Special Cases | Edge cases and exceptions |
|
||||
| Related Flows | Connected user flows |
|
||||
| Technical Notes | Developer-facing details |
|
||||
|
||||
This template is served at `/book/feature-form-samples/template/` as a styled HTML form with placeholder fields. Non-technical team members can understand the structure without reading code.
|
||||
|
||||
## Depots and Larders
|
||||
|
||||
A **depot** is data storage connected to a template. In Atlas, the depot pattern is called a **larder** -- a directory that holds content conforming to a template.
|
||||
|
||||
The connection works like this:
|
||||
|
||||
```
|
||||
Template (structure) + Larder (data) = Templated Book
|
||||
```
|
||||
|
||||
A larder directory contains a `.larder` marker file and organizes content in subdirectories. For feature forms, the larder groups entries by user type:
|
||||
|
||||
```
|
||||
feature-form/
|
||||
├── .larder
|
||||
├── pet-owner/
|
||||
│ ├── register-pet.html
|
||||
│ └── book-appointment.html
|
||||
├── veterinarian/
|
||||
│ └── review-history.html
|
||||
└── backoffice/
|
||||
└── manage-users.html
|
||||
```
|
||||
|
||||
Each file in the larder follows the template's field structure. Atlas renders them through a detail view that reads the content and applies consistent styling.
|
||||
|
||||
## The Larder Pattern
|
||||
|
||||
Larders enforce a constraint: all content in a larder must match the connected template. This keeps documentation consistent even when multiple people contribute.
|
||||
|
||||
The landing page of a templated book links to both:
|
||||
- The **template** -- so you can see the pattern
|
||||
- The **larder** -- so you can browse the actual content
|
||||
|
||||
This separation means the template can evolve independently from the data. Update the template, and all larder entries get the new rendering.
|
||||
|
||||
## Adding a Template
|
||||
|
||||
1. Define the template structure (HTML or markdown) in `soleprint/atlas/templates/` or inside a book's `template/` directory
|
||||
2. Create a larder directory with a `.larder` marker
|
||||
3. Add content files that follow the template structure
|
||||
4. Register the book in `books.json` with `template` metadata
|
||||
5. Add routes in `main.py` for the landing page, template view, and larder browser
|
||||
54
docs/data/en/atlas.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Atlas
|
||||
|
||||
Atlas is the documentation system. It turns structured data into browsable documentation.
|
||||
|
||||
**Mapeando el recorrido** -- mapping the journey.
|
||||
|
||||
---
|
||||
|
||||
## Components
|
||||
|
||||
Atlas has three components:
|
||||
|
||||
| Component | Purpose |
|
||||
|-----------|---------|
|
||||
| **Books** | Documentation libraries. Standalone HTML or template-generated. |
|
||||
| **Templates** | Documentation patterns. Define how content is structured and rendered. |
|
||||
| **Depots** | Data storage. Connect templates to actual content. |
|
||||
|
||||
A book can be standalone -- just HTML files served directly. Or it can be template-backed, where a template defines the structure and a depot provides the data.
|
||||
|
||||
## How It Works
|
||||
|
||||
Atlas runs as a FastAPI app inside soleprint. It serves books at `/book/{slug}/`, fetches data from the soleprint hub, and renders content using Jinja2 templates or static HTML.
|
||||
|
||||
Books are registered in `books.json`. Templates and depots connect through the book's directory structure.
|
||||
|
||||
## Room-Specific Books
|
||||
|
||||
Core books live in `soleprint/atlas/books/`. Room-specific books live in `cfg/<room>/atlas/books/`.
|
||||
|
||||
At build time, room-specific books are merged into the output:
|
||||
|
||||
```
|
||||
soleprint/atlas/books/ # Core books (all rooms)
|
||||
cfg/amar/atlas/books/ # Amar-specific books
|
||||
↓ build.py
|
||||
gen/amar/soleprint/atlas/books/ # Merged output
|
||||
```
|
||||
|
||||
Core books ship with every room. Room books add to or override them. The build copies the core first, then overlays the room-specific content.
|
||||
|
||||
## Data Templates
|
||||
|
||||
Template data files live in `cfg/<room>/data/template/`. These define the structure that depot content must follow.
|
||||
|
||||
## Current State
|
||||
|
||||
| Component | Item | Status |
|
||||
|-----------|------|--------|
|
||||
| Book | Feature Flow Pipeline | ready |
|
||||
| Template | Feature Form | ready |
|
||||
| Depot | Feature Forms | ready |
|
||||
|
||||
See [Books](atlas-books.md) and [Templates](atlas-templates.md) for details on each pattern.
|
||||
54
docs/data/en/components.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Shared Components
|
||||
|
||||
Soleprint has two distributable components. They live inside the spr repo and get published into consuming projects.
|
||||
|
||||
Management is handled by `ctrl/spr.py`.
|
||||
|
||||
## soleprint-ui
|
||||
|
||||
Vue component library. Includes GraphRenderer, sidebar components, and shared UI pieces.
|
||||
|
||||
Source: `soleprint/common/ui/`
|
||||
|
||||
Publish to a consuming project:
|
||||
|
||||
```bash
|
||||
python ctrl/spr.py publish soleprint-ui <target>
|
||||
```
|
||||
|
||||
The target project receives the built files and commits them directly. No npm dependency on spr.
|
||||
|
||||
## soleprint-modelgen
|
||||
|
||||
Model generator. Reads schema definitions and produces model files.
|
||||
|
||||
Source: `soleprint/station/tools/modelgen/`
|
||||
|
||||
Has a `pyproject.toml` for local editable install:
|
||||
|
||||
```bash
|
||||
pip install -e soleprint/station/tools/modelgen/
|
||||
```
|
||||
|
||||
## Registry
|
||||
|
||||
`registry.json` at the repo root defines all components. Each entry has:
|
||||
|
||||
- **name** — component identifier
|
||||
- **type** — `npm` or `python`
|
||||
- **source** — path within the repo
|
||||
- **version** — current version string
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
python ctrl/spr.py list # Show all components
|
||||
python ctrl/spr.py sync <component> <target> # One-time copy
|
||||
python ctrl/spr.py watch <component> <target> # Live sync (ctrl+c to stop)
|
||||
python ctrl/spr.py publish <component> <target> # Versioned publish
|
||||
python ctrl/spr.py diff <component> <target> # Show differences
|
||||
```
|
||||
|
||||
`sync` copies files once. `watch` keeps them in sync while you develop. `publish` stamps a version and copies.
|
||||
|
||||
The consuming project has no awareness of spr. It just commits whatever lands in the target folder.
|
||||
75
docs/data/en/concepts.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Concepts
|
||||
|
||||
The mental model behind soleprint.
|
||||
|
||||
---
|
||||
|
||||
## Rooms
|
||||
|
||||
A room is an isolated configuration. Each room lives in `cfg/<room>/` and contains everything soleprint needs to build and run a specific instance.
|
||||
|
||||
```
|
||||
cfg/
|
||||
standalone/ # Soleprint only, no managed app
|
||||
amar/ # Soleprint wrapping the Amar application
|
||||
myroom/ # Your room
|
||||
```
|
||||
|
||||
Rooms are independent. They don't share state. You can run multiple rooms simultaneously on different ports.
|
||||
|
||||
## Systems
|
||||
|
||||
Three systems plug into the soleprint core:
|
||||
|
||||
- **Artery** — data flow. Connectors to external services. Veins talk to real APIs. Shunts fake them for testing. Pulses compose a vein with a room and depot. Plexus is a full app stack.
|
||||
- **Atlas** — documentation. Books, templates, depots. Documentation that lives next to what it describes and stays actionable.
|
||||
- **Station** — execution. Tools like tester, datagen, modelgen, graphgen. Monitors like databrowse. Desks for task orchestration.
|
||||
|
||||
## The cfg to gen Flow
|
||||
|
||||
`cfg/` is hand-authored. `gen/` is machine-built. Never edit `gen/` directly.
|
||||
|
||||
```
|
||||
cfg/myroom/ ──┐
|
||||
├── build.py ──► gen/myroom/
|
||||
soleprint/ ──┘
|
||||
```
|
||||
|
||||
`build.py` merges the core framework (`soleprint/`) with your room config (`cfg/myroom/`). Room-specific files override or extend core defaults. The output in `gen/myroom/` is what actually runs.
|
||||
|
||||

|
||||
|
||||
## Layers
|
||||
|
||||
Room initialization uses layers 0 through 6. Each layer adds a capability:
|
||||
|
||||
| Layer | What |
|
||||
|-------|------|
|
||||
| 0 | Config — `config.json`, branding, terminology |
|
||||
| 1 | Docker — container setup, compose files |
|
||||
| 2 | Managed app — the application soleprint wraps |
|
||||
| 3 | Link — bridge adapters to the managed app's database |
|
||||
| 4 | Scripts — build and run scripts in `ctrl/` |
|
||||
| 5 | Systems — artery, atlas, station configs |
|
||||
| 6 | Nginx — reverse proxy, sidebar injection |
|
||||
|
||||

|
||||
|
||||
## Standalone vs Managed
|
||||
|
||||
**Standalone** — soleprint runs by itself. No managed app. Useful for tooling, documentation, or connector development.
|
||||
|
||||
**Managed** — soleprint wraps an existing application. Nginx sits in front of the app, injecting the sidebar into every HTML response. Link adapters bridge soleprint into the app's database.
|
||||
|
||||
## The Wrapping Concept
|
||||
|
||||
Soleprint never touches your app's source code. The injection works like this:
|
||||
|
||||
1. Nginx receives the app's HTML response
|
||||
2. `sub_filter` injects soleprint's CSS and JS before `</head>`
|
||||
3. The sidebar renders on top of the app's UI
|
||||
4. Link adapters connect to the app's database for data browsing and test data generation
|
||||
|
||||
The app doesn't know soleprint exists. No SDK. No middleware. No build step changes.
|
||||
|
||||
> Your app runs exactly as it would without soleprint. The sidebar is a layer on top.
|
||||
63
docs/data/en/deployment.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Deployment
|
||||
|
||||
## Docker Compose
|
||||
|
||||
The default. Every built room gets its own compose stack.
|
||||
|
||||
```bash
|
||||
cd gen/<room>/soleprint
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Environment variables in `.env` control the stack:
|
||||
|
||||
- `DEPLOYMENT_NAME` — identifies the deployment
|
||||
- `NETWORK_NAME` — Docker network name
|
||||
- `SOLEPRINT_PORT` — port to expose
|
||||
|
||||
Each room runs independently. No shared state between rooms.
|
||||
|
||||
## Local Development with Caddy
|
||||
|
||||
For multi-room local dev, Caddy acts as a reverse proxy. It routes by hostname.
|
||||
|
||||
Caddyfile location: `~/wdir/ppl/local/Caddyfile`
|
||||
|
||||
Add entries to `/etc/hosts` for each room:
|
||||
|
||||
```
|
||||
127.0.0.1 myroom.local.ar
|
||||
127.0.0.1 myroom.spr.local.ar
|
||||
```
|
||||
|
||||
Routing pattern:
|
||||
|
||||
- `myroom.local.ar` — app direct
|
||||
- `myroom.spr.local.ar` — app with soleprint sidebar
|
||||
|
||||
Caddy reads the hostname and proxies to the right container.
|
||||
|
||||
## AWS Deployment
|
||||
|
||||
Production runs on EC2. Domain: `soleprint.mcrn.ar`.
|
||||
|
||||
Deploy standalone with:
|
||||
|
||||
```bash
|
||||
./ctrl/deploy.sh
|
||||
```
|
||||
|
||||
Services sit on a shared Docker network. Nginx handles routing by subdomain.
|
||||
|
||||
## The Gateway Pattern
|
||||
|
||||
All rooms share one Nginx entry point. One server, one IP, many rooms.
|
||||
|
||||
How it works:
|
||||
|
||||
1. Wildcard DNS: `*.mcrn.ar` points to the EC2 instance.
|
||||
2. Nginx receives the request and reads the hostname.
|
||||
3. Hostname maps to a container on the shared Docker network.
|
||||
4. Nginx proxies to that container.
|
||||
|
||||
No per-room DNS config. Add a room, add an Nginx block, reload. The wildcard handles the rest.
|
||||
52
docs/data/en/intro.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Introduction
|
||||
|
||||
Soleprint is a development workflow platform. It wraps existing applications without touching their source code.
|
||||
|
||||
You get a sidebar injected into your app, connectors to external services, a test runner, data generators, and documentation tools. All running alongside your app, not inside it.
|
||||
|
||||
**Cada paso deja huella** — each step leaves a mark.
|
||||
|
||||
---
|
||||
|
||||
## Why It Exists
|
||||
|
||||
Born from freelance friction. Testing required PRs. Documentation was scattered across wikis and READMEs. Quick API connectors took too long to set up. Every project reinvented the same plumbing.
|
||||
|
||||
Soleprint is the control room that sits next to your app. You build once, reuse everywhere.
|
||||
|
||||
## How It Works
|
||||
|
||||
Soleprint runs as a Docker composition alongside your application. Nginx intercepts the app's HTML response and injects a sidebar via `sub_filter`. The sidebar connects to soleprint's backend, which bridges into the app's database through link adapters.
|
||||
|
||||
Your app stays untouched. No SDK. No middleware. No source changes.
|
||||
|
||||
## The Four Systems
|
||||
|
||||
| System | Purpose |
|
||||
|--------|---------|
|
||||
| **Artery** | Connectors to external services — Jira, Slack, Google, or your own APIs |
|
||||
| **Atlas** | Actionable documentation — books, templates, depots |
|
||||
| **Station** | Tools and execution — tester, datagen, modelgen, graphgen, databrowse |
|
||||
| **Soleprint** | Core coordinator — ties the systems together |
|
||||
|
||||

|
||||
|
||||
## Artery Hierarchy
|
||||
|
||||
Connectors scale from simple to full:
|
||||
|
||||
- **Vein** — stateless API connector
|
||||
- **Shunt** — fake connector for testing
|
||||
- **Pulse** — composed: vein + room + depot
|
||||
- **Plexus** — full app: backend + frontend + database
|
||||
|
||||
## What You Get
|
||||
|
||||
- Sidebar injection into any web app
|
||||
- BDD test runner with Gherkin support
|
||||
- Test data generation with faker
|
||||
- Model generation from schema
|
||||
- Interactive data browser
|
||||
- Navigable model graphs
|
||||
- Reusable API connectors with mock equivalents
|
||||
- Documentation that lives next to the code it describes
|
||||
40
docs/data/en/managed.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Managed Room
|
||||
|
||||
A managed room wraps an existing application. Soleprint runs alongside it, providing tools and a sidebar without touching the app's source code.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
gen/myroom/
|
||||
myapp/ # The app (cloned repos + Docker)
|
||||
link/ # DB bridge (FastAPI adapter)
|
||||
soleprint/ # Soleprint instance
|
||||
```
|
||||
|
||||
## Wrapping mechanism
|
||||
|
||||
Nginx `sub_filter` injects sidebar CSS and JS into the app's HTML `</head>` tag. The app serves normally — soleprint attaches from the outside.
|
||||
|
||||

|
||||
|
||||
## config.json
|
||||
|
||||
A managed room adds these fields to `config.json`:
|
||||
|
||||
- `managed.name` — the app name
|
||||
- `managed.repos.backend` — backend repository
|
||||
- `managed.repos.frontend` — frontend repository
|
||||
|
||||
## Sidebar
|
||||
|
||||
Loads from `/spr/sidebar.js` and `/spr/sidebar.css`, configured via `/api/sidebar/config`.
|
||||
|
||||
The sidebar is generic at runtime. All customization comes from `config.json`.
|
||||
|
||||
## Hosts
|
||||
|
||||
Add to `/etc/hosts`:
|
||||
|
||||
```
|
||||
127.0.0.1 myroom.spr.local.ar myroom.local.ar
|
||||
```
|
||||
87
docs/data/en/quickstart.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Quick Start
|
||||
|
||||
Zero to running in 2 minutes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.12+
|
||||
- Docker
|
||||
|
||||
## Setup
|
||||
|
||||
**1. Clone the repo**
|
||||
|
||||
```bash
|
||||
git clone <repo-url> spr
|
||||
cd spr
|
||||
```
|
||||
|
||||
**2. Initialize a room**
|
||||
|
||||
```bash
|
||||
python -m init.cli myroom
|
||||
```
|
||||
|
||||
The interactive wizard walks you through layers 0-6. Accept the defaults for a standalone setup.
|
||||
|
||||
**3. Build**
|
||||
|
||||
```bash
|
||||
python build.py --cfg myroom
|
||||
```
|
||||
|
||||
This merges core framework files with your room config into `gen/myroom/`.
|
||||
|
||||
**4. Run**
|
||||
|
||||
```bash
|
||||
cd gen/myroom && docker compose up
|
||||
```
|
||||
|
||||
**5. Open**
|
||||
|
||||
Visit [http://localhost:12000](http://localhost:12000).
|
||||
|
||||
---
|
||||
|
||||
## Alternative: Browser Wizard
|
||||
|
||||
Prefer a UI? Run the web initializer:
|
||||
|
||||
```bash
|
||||
python -m init.web
|
||||
```
|
||||
|
||||
Open [http://localhost:9000](http://localhost:9000) and configure your room from the browser.
|
||||
|
||||
## Clone an Existing Room
|
||||
|
||||
Start from a sample configuration:
|
||||
|
||||
```bash
|
||||
python -m init.cli myroom --from sample
|
||||
```
|
||||
|
||||
This copies the sample room's config as your starting point.
|
||||
|
||||
## Rebuild
|
||||
|
||||
After changing anything in `cfg/myroom/`, rebuild:
|
||||
|
||||
```bash
|
||||
python build.py --cfg myroom
|
||||
```
|
||||
|
||||
Then restart the containers.
|
||||
|
||||
## Build All Rooms
|
||||
|
||||
```bash
|
||||
python build.py --all
|
||||
```
|
||||
|
||||
## Ports
|
||||
|
||||
| Service | Port |
|
||||
|---------|------|
|
||||
| Soleprint | 12000 |
|
||||
42
docs/data/en/room-setup.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Room Setup
|
||||
|
||||
Two ways to create a room: CLI wizard or web wizard.
|
||||
|
||||
```bash
|
||||
# CLI wizard
|
||||
python -m init.cli myroom
|
||||
|
||||
# Web wizard (opens browser on :9000)
|
||||
python -m init.web
|
||||
|
||||
# Clone from existing room
|
||||
python -m init.cli myroom --from sample
|
||||
```
|
||||
|
||||
## Layers
|
||||
|
||||
Each layer is optional beyond layer 0.
|
||||
|
||||
| Layer | What | Files |
|
||||
|-------|------|-------|
|
||||
| 0 | Config + Data | `config.json`, `data/*.json` |
|
||||
| 1 | Docker | `soleprint/docker-compose.yml`, `.env` |
|
||||
| 2 | Managed App | `docker-compose.yml`, Dockerfiles, `.env` |
|
||||
| 3 | Link | `link/main.py`, `adapters/`, Dockerfile |
|
||||
| 4 | Scripts | `ctrl/start.sh`, `stop.sh`, `status.sh`, `logs.sh` |
|
||||
| 5 | Systems | tester environments, test scaffolds |
|
||||
| 6 | Nginx | `nginx/local.conf`, `docker-compose.nginx.yml` |
|
||||
|
||||

|
||||
|
||||
The wizard adds layers incrementally. Layer 0 is always created. Each subsequent layer builds on the previous ones but none are required.
|
||||
|
||||
## Build
|
||||
|
||||
After the wizard finishes, build the room:
|
||||
|
||||
```bash
|
||||
python build.py --cfg myroom
|
||||
```
|
||||
|
||||
Output goes to `gen/myroom/`. The build merges room-specific configs from `cfg/myroom/` into the base framework.
|
||||
46
docs/data/en/standalone.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Standalone Room
|
||||
|
||||
A standalone room is soleprint by itself — no managed app. Good for documentation, tool development, or running the platform independently.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
cfg/standalone/
|
||||
config.json
|
||||
data/*.json # 12 registry files
|
||||
soleprint/
|
||||
docker-compose.yml
|
||||
```
|
||||
|
||||
Build output is flat — all systems merged into one directory:
|
||||
|
||||
```
|
||||
gen/standalone/
|
||||
```
|
||||
|
||||
## config.json
|
||||
|
||||
Three sections:
|
||||
|
||||
- **framework** — name, port
|
||||
- **systems** — artery, atlas, station toggles and settings
|
||||
- **components** — the naming scheme used across the room
|
||||
|
||||
## Data registries
|
||||
|
||||
The `data/*.json` files are registries: `veins.json`, `tools.json`, `books.json`, etc.
|
||||
|
||||
Each follows the same shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "...",
|
||||
"slug": "...",
|
||||
"title": "...",
|
||||
"status": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
80
docs/data/en/station-databrowse.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Databrowse
|
||||
|
||||
SQL data browser. Connects to a database, reads its schema from config, and provides a navigation and query interface.
|
||||
|
||||
**Status:** ready
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
Databrowse is a monitor, not a tool. It runs continuously and lets you browse database contents through a web interface. Navigate tables, inspect rows, run saved queries.
|
||||
|
||||
The core is generic SQL. Room configuration defines the schema and saved views.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
soleprint/station/monitors/databrowse/ # Core (generic SQL browser)
|
||||
cfg/<room>/soleprint/station/monitors/databrowse/depot/ # Room config
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Room-specific config lives in the depot directory.
|
||||
|
||||
### schema.json
|
||||
|
||||
Defines tables, fields, and relationships:
|
||||
|
||||
```json
|
||||
{
|
||||
"tables": [
|
||||
{
|
||||
"name": "users",
|
||||
"fields": [
|
||||
{"name": "id", "type": "integer", "primary": true},
|
||||
{"name": "email", "type": "string"},
|
||||
{"name": "created_at", "type": "datetime"}
|
||||
],
|
||||
"relationships": [
|
||||
{"field": "id", "target": "orders.user_id", "type": "one_to_many"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### views.json
|
||||
|
||||
Defines saved queries:
|
||||
|
||||
```json
|
||||
{
|
||||
"views": [
|
||||
{
|
||||
"name": "Recent Users",
|
||||
"query": "SELECT * FROM users ORDER BY created_at DESC LIMIT 50"
|
||||
},
|
||||
{
|
||||
"name": "Active Orders",
|
||||
"query": "SELECT * FROM orders WHERE status = 'active'"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Separation
|
||||
|
||||
Core provides:
|
||||
- SQL connection handling
|
||||
- Table navigation UI
|
||||
- Query execution engine
|
||||
- Relationship traversal
|
||||
|
||||
Room provides:
|
||||
- `depot/schema.json` -- table definitions
|
||||
- `depot/views.json` -- saved queries
|
||||
- Database connection credentials
|
||||
|
||||
The core knows nothing about your domain. The depot tells it what to show.
|
||||
57
docs/data/en/station-datagen.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Datagen
|
||||
|
||||
Test data generator using faker. Produces realistic, domain-specific data for testing and development.
|
||||
|
||||
**Status:** live
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
Datagen generates fake but realistic data. Names, emails, addresses, transactions -- whatever your domain needs. It uses Python's faker library under the hood.
|
||||
|
||||
Core datagen is a placeholder. The real work happens in room-specific generators.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
soleprint/station/tools/datagen/ # Core (base classes, placeholder)
|
||||
cfg/<room>/soleprint/station/tools/datagen/ # Room-specific generators
|
||||
```
|
||||
|
||||
After build, both merge into `gen/<room>/station/tools/datagen/`.
|
||||
|
||||
## Pattern
|
||||
|
||||
Rooms subclass a base generator and provide domain-specific data factories:
|
||||
|
||||
```python
|
||||
from station.tools.datagen.base import BaseGenerator
|
||||
|
||||
class AmarDataGenerator(BaseGenerator):
|
||||
def generate_customers(self, count=10):
|
||||
return [self.fake_customer() for _ in range(count)]
|
||||
|
||||
def fake_customer(self):
|
||||
return {
|
||||
"name": self.faker.name(),
|
||||
"email": self.faker.email(),
|
||||
"phone": self.faker.phone_number(),
|
||||
}
|
||||
```
|
||||
|
||||
Each room defines what data it needs. Core provides the faker instance and base class. Rooms provide the factories.
|
||||
|
||||
## Room Configuration
|
||||
|
||||
Room generators live in `cfg/<room>/soleprint/station/tools/datagen/`. They are fully self-contained -- they define their own models, factories, and output formats.
|
||||
|
||||
The core module provides:
|
||||
- Base generator class with faker instance
|
||||
- CLI entry point
|
||||
- Output formatting (JSON, CSV)
|
||||
|
||||
Rooms provide:
|
||||
- Domain-specific generator subclasses
|
||||
- Field definitions and relationships
|
||||
- Volume and distribution configuration
|
||||
38
docs/data/en/station-graphgen.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Graphgen
|
||||
|
||||
Interactive database schema visualization. Supabase-style graph of your data model, rendered in the browser.
|
||||
|
||||
**Status:** planned
|
||||
|
||||
---
|
||||
|
||||
## What It Will Do
|
||||
|
||||
Graphgen will take a schema definition and render it as an interactive, navigable graph. Tables as nodes, relationships as edges. Click to explore, zoom to navigate.
|
||||
|
||||
Think Supabase's schema visualizer, but fed by soleprint's modelgen extractors and rendered with soleprint-ui's GraphRenderer.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Extract (modelgen) ──► Serve (station API) ──► Render (GraphRenderer)
|
||||
```
|
||||
|
||||
**Extract** -- modelgen extractors read the codebase (Django, SQLAlchemy, Prisma) and produce a normalized schema.
|
||||
|
||||
**Serve** -- station exposes the schema as a JSON API endpoint.
|
||||
|
||||
**Render** -- GraphRenderer (Vue Flow) draws the interactive graph in the browser.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **modelgen extractors** -- must be functional before graphgen can extract schemas
|
||||
- **soleprint-ui GraphRenderer** -- Vue Flow-based component for rendering
|
||||
|
||||
Graphgen depends on modelgen extractors being complete. That is the blocking dependency.
|
||||
|
||||
## Location
|
||||
|
||||
```
|
||||
soleprint/station/tools/graphgen/ # Core (not yet built)
|
||||
```
|
||||
54
docs/data/en/station-modelgen.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Modelgen
|
||||
|
||||
Generates platform-specific models from JSON Schema. Reads schema once, writes models for multiple targets.
|
||||
|
||||
**Status:** dev
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
Modelgen takes a JSON Schema definition and produces model code for different platforms:
|
||||
|
||||
- **Pydantic** -- Python data validation models
|
||||
- **Django ORM** -- Django model classes
|
||||
- **Prisma** -- Prisma schema definitions
|
||||
|
||||
One schema, multiple outputs.
|
||||
|
||||
## Extractors
|
||||
|
||||
Modelgen also works in reverse. Extractors read existing codebases and produce a normalized schema representation:
|
||||
|
||||
- **Django extractor** -- reads Django model files
|
||||
- **SQLAlchemy extractor** -- reads SQLAlchemy model files
|
||||
- **Prisma extractor** -- reads Prisma schema files
|
||||
|
||||
Extractors feed into graphgen for visualization.
|
||||
|
||||
## Output
|
||||
|
||||
Generated models are written to `gen/<room>/models/`.
|
||||
|
||||
```
|
||||
gen/<room>/models/
|
||||
├── pydantic/
|
||||
├── django/
|
||||
└── prisma/
|
||||
```
|
||||
|
||||
## CLI
|
||||
|
||||
```bash
|
||||
python -m modelgen
|
||||
```
|
||||
|
||||
Reads from `schema.json` (the project source of truth) and writes to the configured output directory.
|
||||
|
||||
## Shared Distribution
|
||||
|
||||
Modelgen is also distributed as a shared component via `ctrl/spr.py`. This allows other projects to use model generation without running full soleprint.
|
||||
|
||||
## Schema Source
|
||||
|
||||
The source of truth is `schema.json` at the project root. All model generation starts from this file. Room-specific schema extensions live in `cfg/<room>/models/`.
|
||||
99
docs/data/en/station-tester.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Tester
|
||||
|
||||
HTTP contract test runner with web UI and CLI. Tests API endpoints against configurable environments with support for multiple auth types.
|
||||
|
||||
**Status:** live
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
Tester runs HTTP requests against real endpoints and validates responses. It is not a unit test runner. It tests contracts -- does this endpoint return what the spec says it should?
|
||||
|
||||
Tests are written as Python classes extending `ContractTestCase`. They run via pytest or through the soleprint web UI.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environments
|
||||
|
||||
Defined in `environments.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"environments": [
|
||||
{
|
||||
"name": "local",
|
||||
"url": "http://localhost:8000",
|
||||
"auth_type": "none"
|
||||
},
|
||||
{
|
||||
"name": "staging",
|
||||
"url": "https://staging.example.com",
|
||||
"auth_type": "bearer",
|
||||
"token_endpoint": "/api/token/"
|
||||
},
|
||||
{
|
||||
"name": "external",
|
||||
"url": "https://api.example.com",
|
||||
"auth_type": "api-key"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Auth types: `bearer`, `api-key`, `none`.
|
||||
|
||||
## Base Class
|
||||
|
||||
All tests extend `ContractTestCase`:
|
||||
|
||||
```python
|
||||
from station.tools.tester.base import ContractTestCase
|
||||
|
||||
class TestUserEndpoints(ContractTestCase):
|
||||
AUTH_TYPE = "bearer"
|
||||
TOKEN_ENDPOINT = "/api/token/"
|
||||
|
||||
def test_list_users(self):
|
||||
response = self.get("/api/users/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
```
|
||||
|
||||
`ContractTestCase` handles auth negotiation, environment selection, and base URL resolution.
|
||||
|
||||
## Test Discovery
|
||||
|
||||
Tests live in two places:
|
||||
|
||||
- **Core tests:** `soleprint/station/tools/tester/tests/` -- shared across all rooms
|
||||
- **Room tests:** `cfg/<room>/soleprint/station/tools/tester/tests/` -- room-specific
|
||||
|
||||
Room tests import from core:
|
||||
|
||||
```python
|
||||
from station.tools.tester.base import ContractTestCase
|
||||
```
|
||||
|
||||
After build, both are merged into `gen/<room>/station/tools/tester/tests/`.
|
||||
|
||||
## Helpers
|
||||
|
||||
Built-in test helpers:
|
||||
|
||||
- `unique_email()` -- generates a unique email address
|
||||
- `unique_id()` -- generates a unique identifier
|
||||
|
||||
These are generic helpers available to all rooms. Room-specific helpers stay in `cfg/<room>/` and are not part of core.
|
||||
|
||||
## Running
|
||||
|
||||
**Web UI:** navigate to `/station/tools/tester/` in soleprint.
|
||||
|
||||
**CLI:**
|
||||
|
||||
```bash
|
||||
cd gen/<room>
|
||||
pytest station/tools/tester/tests/
|
||||
```
|
||||
|
||||
Environment selection is handled via config or CLI flags.
|
||||
71
docs/data/en/station.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Station
|
||||
|
||||
Station is the execution system. It runs tools, monitors environments, and bundles them into composable desks.
|
||||
|
||||
**Centro de control** -- the control center.
|
||||
|
||||
---
|
||||
|
||||
## Hierarchy
|
||||
|
||||
Station components scale from single-purpose to composed:
|
||||
|
||||
```
|
||||
Tool ──────► Desk
|
||||
│ │
|
||||
│ └── Composed: Cabinet + Room + Depots
|
||||
│
|
||||
└── Standalone executable (tester, datagen, modelgen, graphgen)
|
||||
|
||||
Monitor ─── Long-running observer (databrowse)
|
||||
```
|
||||
|
||||
**Tool** -- a standalone executable that does one job. Generates data, runs tests, produces models. Each tool works independently and can be invoked via web UI or CLI.
|
||||
|
||||
**Monitor** -- a long-running observer. Connects to a data source and provides a browsing or query interface. Always on, not invoked per-task.
|
||||
|
||||
**Desk** -- a composed execution bundle. Combines a cabinet (tool configuration), a room, and depots (data sources) into a ready-to-run environment.
|
||||
|
||||
## Tools
|
||||
|
||||
| Tool | Status | Description |
|
||||
|------|--------|-------------|
|
||||
| [Tester](station-tester.md) | live | HTTP contract test runner, multi-environment, BDD/Gherkin |
|
||||
| [Datagen](station-datagen.md) | live | Test data generator using faker |
|
||||
| [Modelgen](station-modelgen.md) | dev | Generate models from JSON Schema (Pydantic, Django, Prisma) |
|
||||
| [Graphgen](station-graphgen.md) | planned | Supabase-style interactive DB schema visualization |
|
||||
|
||||
## Monitors
|
||||
|
||||
| Monitor | Status | Description |
|
||||
|---------|--------|-------------|
|
||||
| [Databrowse](station-databrowse.md) | ready | SQL data browser |
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
station/
|
||||
├── tools/
|
||||
│ ├── tester/ # HTTP contract testing
|
||||
│ ├── datagen/ # Test data generation
|
||||
│ ├── modelgen/ # Model generation from schema
|
||||
│ └── graphgen/ # Schema visualization (planned)
|
||||
├── monitors/
|
||||
│ └── databrowse/ # SQL data browser
|
||||
└── desks/ # Composed execution bundles
|
||||
```
|
||||
|
||||
## Room Configuration
|
||||
|
||||
Tools and monitors follow the same split as all soleprint systems. Core logic lives in `soleprint/station/`. Room-specific configuration lives in `cfg/<room>/soleprint/station/`.
|
||||
|
||||
```
|
||||
cfg/<room>/soleprint/station/
|
||||
├── tools/
|
||||
│ ├── tester/tests/ # Room-specific test cases
|
||||
│ └── datagen/ # Room-specific data generators
|
||||
└── monitors/
|
||||
└── databrowse/depot/ # Room-specific schema and views
|
||||
```
|
||||
|
||||
The build merges both into `gen/<room>/`.
|
||||
29
docs/data/topics.json
Normal file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
{"id": "intro", "title": {"en": "Introduction"}},
|
||||
{"id": "quickstart", "title": {"en": "Quick Start"}},
|
||||
{"id": "concepts", "title": {"en": "Concepts"}},
|
||||
{"id": "room-setup", "title": {"en": "↳ Room Setup"}, "sub": true},
|
||||
{"id": "standalone", "title": {"en": "↳ Standalone"}, "sub": true},
|
||||
{"id": "managed", "title": {"en": "↳ Managed"}, "sub": true},
|
||||
|
||||
{"id": "artery", "title": {"en": "Artery"}},
|
||||
{"id": "artery-jira", "title": {"en": "↳ Jira"}, "sub": true},
|
||||
{"id": "artery-google", "title": {"en": "↳ Google"}, "sub": true},
|
||||
{"id": "artery-slack", "title": {"en": "↳ Slack"}, "sub": true},
|
||||
{"id": "artery-ia", "title": {"en": "↳ IA"}, "sub": true},
|
||||
{"id": "artery-shunts", "title": {"en": "↳ Shunts"}, "sub": true},
|
||||
|
||||
{"id": "atlas", "title": {"en": "Atlas"}},
|
||||
{"id": "atlas-books", "title": {"en": "↳ Books"}, "sub": true},
|
||||
{"id": "atlas-templates", "title": {"en": "↳ Templates"}, "sub": true},
|
||||
|
||||
{"id": "station", "title": {"en": "Station"}},
|
||||
{"id": "station-tester", "title": {"en": "↳ Tester"}, "sub": true},
|
||||
{"id": "station-datagen", "title": {"en": "↳ Datagen"}, "sub": true},
|
||||
{"id": "station-modelgen", "title": {"en": "↳ Modelgen"}, "sub": true},
|
||||
{"id": "station-graphgen", "title": {"en": "↳ Graphgen"}, "sub": true},
|
||||
{"id": "station-databrowse", "title": {"en": "↳ Databrowse"}, "sub": true},
|
||||
|
||||
{"id": "components", "title": {"en": "Shared Components"}},
|
||||
{"id": "deployment", "title": {"en": "Deployment"}}
|
||||
]
|
||||
347
docs/docs.css
Normal file
@@ -0,0 +1,347 @@
|
||||
/* soleprint docs — minimal-neon */
|
||||
|
||||
:root {
|
||||
--bg: #0a0a0a;
|
||||
--surface: #1a1a1a;
|
||||
--border: #333;
|
||||
--text: #e5e5e5;
|
||||
--text-muted: #a3a3a3;
|
||||
--text-dim: #666;
|
||||
--amber: #d4a574;
|
||||
--amber-dim: #b8956a;
|
||||
|
||||
--artery: #b91c1c;
|
||||
--artery-text: #fca5a5;
|
||||
--atlas: #15803d;
|
||||
--atlas-text: #86efac;
|
||||
--station: #1d4ed8;
|
||||
--station-text: #93c5fd;
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
.layout {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
width: 220px;
|
||||
flex-shrink: 0;
|
||||
background: var(--surface);
|
||||
border-right: 1px solid var(--border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
padding: 1.5rem 0;
|
||||
}
|
||||
|
||||
/* Hide sidebar scrollbar */
|
||||
.sidebar::-webkit-scrollbar { width: 0; }
|
||||
.sidebar { scrollbar-width: none; }
|
||||
|
||||
.sidebar-header {
|
||||
padding: 0 1rem 1rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sidebar-header a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar-header h1 {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.sidebar-header span {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
display: block;
|
||||
padding: 0.4rem 1rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
border-left: 2px solid transparent;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.sidebar-item:hover {
|
||||
color: var(--text);
|
||||
background: rgba(255,255,255,0.03);
|
||||
}
|
||||
|
||||
.sidebar-item.active {
|
||||
color: var(--amber);
|
||||
border-left-color: var(--amber);
|
||||
background: rgba(212,165,116,0.05);
|
||||
}
|
||||
|
||||
.sidebar-chevron {
|
||||
display: inline-block;
|
||||
margin-right: 0.3rem;
|
||||
transition: transform 0.15s;
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.sidebar-chevron.expanded {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.sidebar-sub {
|
||||
padding-left: 1.75rem;
|
||||
font-size: 0.8rem;
|
||||
border-left-color: transparent;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.sidebar-sub:hover {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.sidebar-sub.active {
|
||||
color: var(--amber);
|
||||
border-left-color: var(--amber);
|
||||
background: rgba(212,165,116,0.05);
|
||||
}
|
||||
|
||||
/* System-colored sidebar items */
|
||||
.sidebar-item[href*="artery"]:hover,
|
||||
.sidebar-sub[href*="artery"]:hover { color: var(--artery-text); }
|
||||
.sidebar-item[href*="artery"].active,
|
||||
.sidebar-sub[href*="artery"].active { color: var(--artery-text); border-left-color: var(--artery); }
|
||||
|
||||
.sidebar-item[href*="atlas"]:hover,
|
||||
.sidebar-sub[href*="atlas"]:hover { color: var(--atlas-text); }
|
||||
.sidebar-item[href*="atlas"].active,
|
||||
.sidebar-sub[href*="atlas"].active { color: var(--atlas-text); border-left-color: var(--atlas); }
|
||||
|
||||
.sidebar-item[href*="station"]:hover,
|
||||
.sidebar-sub[href*="station"]:hover { color: var(--station-text); }
|
||||
.sidebar-item[href*="station"].active,
|
||||
.sidebar-sub[href*="station"].active { color: var(--station-text); border-left-color: var(--station); }
|
||||
|
||||
/* Content */
|
||||
.content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
max-width: 800px;
|
||||
padding: 2rem 3rem;
|
||||
}
|
||||
|
||||
.loading {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
/* Markdown rendering */
|
||||
.content h1 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: var(--amber);
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.content h3 {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.content p {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 0.75rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.content strong {
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.content a {
|
||||
color: var(--amber);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.content blockquote {
|
||||
border-left: 3px solid var(--amber);
|
||||
padding: 0.75rem 1.25rem;
|
||||
margin: 1rem 0;
|
||||
background: var(--surface);
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.content blockquote p {
|
||||
margin-bottom: 0;
|
||||
color: var(--amber);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.content ul, .content ol {
|
||||
padding-left: 0;
|
||||
margin: 0.75rem 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.content li {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
padding-left: 1.25rem;
|
||||
margin-bottom: 0.4rem;
|
||||
position: relative;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.content li::before {
|
||||
content: ">";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--amber);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.content hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--border);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.content pre {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
overflow-x: auto;
|
||||
border-radius: 8px;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.content code {
|
||||
font-family: ui-monospace, "SF Mono", "Cascadia Mono", monospace;
|
||||
color: var(--amber);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.content pre code {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.content table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.content th {
|
||||
text-align: left;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-bottom: 2px solid var(--border);
|
||||
color: var(--amber);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.content td {
|
||||
padding: 0.4rem 0.75rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
color: var(--text-muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.content tr:hover td {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
/* Graph images inline */
|
||||
.content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.layout {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
position: static;
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
gap: 0;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.sidebar-header { display: none; }
|
||||
|
||||
.sidebar-item {
|
||||
border-left: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
white-space: nowrap;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.sidebar-item.active {
|
||||
border-bottom-color: var(--amber);
|
||||
border-left: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar-sub {
|
||||
padding-left: 0.75rem;
|
||||
border-left: none;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
}
|
||||
318
docs/docs.js
Normal file
@@ -0,0 +1,318 @@
|
||||
// soleprint docs — sidebar + markdown renderer
|
||||
// Logic adapted from mcrn.ar/design, reskinned for minimal-neon
|
||||
|
||||
const state = {
|
||||
lang: "en",
|
||||
topics: [],
|
||||
contentCache: {},
|
||||
activeTopic: null,
|
||||
expandedGroup: null,
|
||||
};
|
||||
|
||||
const dom = {
|
||||
sidebar: () => document.getElementById("sidebar"),
|
||||
content: () => document.getElementById("content"),
|
||||
};
|
||||
|
||||
// --- Topic grouping ---
|
||||
|
||||
function buildGroups(topics) {
|
||||
const groups = [];
|
||||
for (const t of topics) {
|
||||
if (!t.sub) {
|
||||
groups.push({ parent: t, subs: [] });
|
||||
} else if (groups.length > 0) {
|
||||
groups[groups.length - 1].subs.push(t);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
function findParentGroup(topicId) {
|
||||
for (const g of buildGroups(state.topics)) {
|
||||
if (g.parent.id === topicId || g.subs.some((s) => s.id === topicId)) {
|
||||
return g.parent.id;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- Sidebar ---
|
||||
|
||||
function renderSidebar() {
|
||||
const groups = buildGroups(state.topics);
|
||||
const items = [];
|
||||
|
||||
items.push(`<div class="sidebar-header"><a href="#intro"><h1>soleprint</h1><span>docs</span></a></div>`);
|
||||
|
||||
for (const g of groups) {
|
||||
const isExpanded = state.expandedGroup === g.parent.id;
|
||||
const hasSubs = g.subs.length > 0;
|
||||
|
||||
items.push(parentItem(g.parent, hasSubs, isExpanded));
|
||||
|
||||
if (isExpanded && hasSubs) {
|
||||
for (const s of g.subs) {
|
||||
items.push(subItem(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dom.sidebar().innerHTML = items.join("");
|
||||
bindParentClicks();
|
||||
}
|
||||
|
||||
function parentItem(topic, hasSubs, isExpanded) {
|
||||
const active = state.activeTopic === topic.id ? " active" : "";
|
||||
const chevron = hasSubs
|
||||
? `<span class="sidebar-chevron${isExpanded ? " expanded" : ""}">›</span>`
|
||||
: "";
|
||||
const label = topic.title[state.lang] || topic.title.en;
|
||||
return `<a class="sidebar-item${active}" href="#${topic.id}" data-group="${topic.id}">${chevron}${label}</a>`;
|
||||
}
|
||||
|
||||
function subItem(topic) {
|
||||
const active = state.activeTopic === topic.id ? " active" : "";
|
||||
const label = topic.title[state.lang] || topic.title.en;
|
||||
return `<a class="sidebar-item sidebar-sub${active}" href="#${topic.id}">${label}</a>`;
|
||||
}
|
||||
|
||||
function bindParentClicks() {
|
||||
dom.sidebar().querySelectorAll(".sidebar-item:not(.sidebar-sub)").forEach((el) => {
|
||||
el.addEventListener("click", (e) => {
|
||||
const groupId = el.dataset.group;
|
||||
const group = buildGroups(state.topics).find((g) => g.parent.id === groupId);
|
||||
|
||||
if (group?.subs.length && state.expandedGroup === groupId && state.activeTopic === groupId) {
|
||||
e.preventDefault();
|
||||
state.expandedGroup = null;
|
||||
renderSidebar();
|
||||
} else {
|
||||
state.expandedGroup = groupId;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --- Content loading ---
|
||||
|
||||
async function loadTopic(id) {
|
||||
const el = dom.content();
|
||||
const cacheKey = `${state.lang}:${id}`;
|
||||
|
||||
if (state.contentCache[cacheKey]) {
|
||||
el.innerHTML = state.contentCache[cacheKey];
|
||||
} else {
|
||||
el.innerHTML = '<p class="loading">Loading...</p>';
|
||||
try {
|
||||
const md = await fetchMarkdown(id);
|
||||
const html = markdown.render(md);
|
||||
state.contentCache[cacheKey] = html;
|
||||
el.innerHTML = html;
|
||||
} catch (e) {
|
||||
el.innerHTML = `<p style="color:var(--artery-text);">Failed to load: ${e.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
el.scrollTop = 0;
|
||||
}
|
||||
|
||||
async function fetchMarkdown(id) {
|
||||
let resp = await fetch(`data/${state.lang}/${id}.md`);
|
||||
if (!resp.ok && state.lang !== "en") {
|
||||
resp = await fetch(`data/en/${id}.md`);
|
||||
}
|
||||
if (!resp.ok) throw new Error("Not found");
|
||||
return resp.text();
|
||||
}
|
||||
|
||||
// --- Markdown renderer ---
|
||||
|
||||
const markdown = {
|
||||
render(md) {
|
||||
const lines = md.split("\n");
|
||||
const parts = [];
|
||||
let i = 0;
|
||||
|
||||
while (i < lines.length) {
|
||||
const trimmed = lines[i].trim();
|
||||
if (!trimmed) { i++; continue; }
|
||||
const [html, next] = this.parseLine(lines, i, trimmed);
|
||||
if (html) parts.push(html);
|
||||
i = next;
|
||||
}
|
||||
|
||||
return parts.join("");
|
||||
},
|
||||
|
||||
parseLine(lines, i, trimmed) {
|
||||
for (const parser of this.parsers) {
|
||||
if (parser.match(trimmed)) {
|
||||
return parser.parse(lines, i, trimmed);
|
||||
}
|
||||
}
|
||||
return [`<p>${this.inline(trimmed)}</p>`, i + 1];
|
||||
},
|
||||
|
||||
parsers: [
|
||||
{
|
||||
name: "fenced-code",
|
||||
match: (t) => t.startsWith("```"),
|
||||
parse(lines, i, trimmed) {
|
||||
const lang = trimmed.slice(3).trim();
|
||||
const codeLines = [];
|
||||
i++;
|
||||
while (i < lines.length && !lines[i].trim().startsWith("```")) {
|
||||
codeLines.push(markdown.escape(lines[i]));
|
||||
i++;
|
||||
}
|
||||
return [`<pre><code>${codeLines.join("\n")}</code></pre>`, i + 1];
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "hr",
|
||||
match: (t) => /^---+$/.test(t),
|
||||
parse(_, i) { return ["<hr>", i + 1]; },
|
||||
},
|
||||
{
|
||||
name: "table",
|
||||
match: (t) => t.startsWith("|"),
|
||||
parse(lines, i) {
|
||||
const rows = [];
|
||||
while (i < lines.length && lines[i].trim().startsWith("|")) {
|
||||
rows.push(lines[i].trim());
|
||||
i++;
|
||||
}
|
||||
return [markdown.table(rows), i];
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "h3",
|
||||
match: (t) => t.startsWith("### "),
|
||||
parse(_, i, t) { return [`<h3>${markdown.inline(t.slice(4))}</h3>`, i + 1]; },
|
||||
},
|
||||
{
|
||||
name: "h2",
|
||||
match: (t) => t.startsWith("## "),
|
||||
parse(_, i, t) { return [`<h2>${markdown.inline(t.slice(3))}</h2>`, i + 1]; },
|
||||
},
|
||||
{
|
||||
name: "h1",
|
||||
match: (t) => t.startsWith("# "),
|
||||
parse(_, i, t) { return [`<h1>${markdown.inline(t.slice(2))}</h1>`, i + 1]; },
|
||||
},
|
||||
{
|
||||
name: "blockquote",
|
||||
match: (t) => t.startsWith("> ") || t === ">",
|
||||
parse(lines, i) {
|
||||
const content = [];
|
||||
while (i < lines.length) {
|
||||
const ql = lines[i].trim();
|
||||
if (ql.startsWith("> ")) content.push(ql.slice(2));
|
||||
else if (ql === ">") content.push("");
|
||||
else break;
|
||||
i++;
|
||||
}
|
||||
const inner = content.map((l) => `<p>${markdown.inline(l)}</p>`).join("");
|
||||
return [`<blockquote>${inner}</blockquote>`, i];
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "image",
|
||||
match: (t) => /^!\[.*\]\(.*\)$/.test(t),
|
||||
parse(_, i, t) {
|
||||
const m = t.match(/^!\[(.*?)\]\((.*?)\)$/);
|
||||
if (m) {
|
||||
const alt = m[1];
|
||||
const src = m[2];
|
||||
return [`<a href="viewer.html?src=${encodeURIComponent(src)}"><img src="${src}" alt="${alt}" title="Click to expand"></a>`, i + 1];
|
||||
}
|
||||
return [`<p>${t}</p>`, i + 1];
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list",
|
||||
match: (t) => t.startsWith("- "),
|
||||
parse(lines, i) {
|
||||
const items = [];
|
||||
while (i < lines.length && lines[i].trim().startsWith("- ")) {
|
||||
items.push(lines[i].trim().slice(2));
|
||||
i++;
|
||||
}
|
||||
const inner = items.map((item) => `<li>${markdown.inline(item)}</li>`).join("");
|
||||
return [`<ul>${inner}</ul>`, i];
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
table(rows) {
|
||||
if (rows.length < 2) return "";
|
||||
const split = (line) => line.split("|").slice(1, -1).map((c) => c.trim());
|
||||
|
||||
const headers = split(rows[0]);
|
||||
const body = rows.slice(2).map(split);
|
||||
|
||||
const thead = headers.some((h) => h)
|
||||
? `<thead><tr>${headers.map((h) => `<th>${this.inline(h)}</th>`).join("")}</tr></thead>`
|
||||
: "";
|
||||
const tbody = body
|
||||
.map((row) => `<tr>${row.map((c) => `<td>${this.inline(c)}</td>`).join("")}</tr>`)
|
||||
.join("");
|
||||
|
||||
return `<table>${thead}<tbody>${tbody}</tbody></table>`;
|
||||
},
|
||||
|
||||
inlineRules: [
|
||||
{ pattern: /\*\*(.+?)\*\*/g, tag: "strong" },
|
||||
{ pattern: /\*(.+?)\*/g, tag: "em" },
|
||||
{ pattern: /`(.+?)`/g, tag: "code" },
|
||||
{ pattern: /\[(.+?)\]\((.+?)\)/g, render: (_, text, href) => `<a href="${href}">${text}</a>` },
|
||||
],
|
||||
|
||||
inline(text) {
|
||||
if (!text) return "";
|
||||
return this.inlineRules.reduce((result, rule) => {
|
||||
const replacer = rule.render || ((_, content) => `<${rule.tag}>${content}</${rule.tag}>`);
|
||||
return result.replace(rule.pattern, replacer);
|
||||
}, text);
|
||||
},
|
||||
|
||||
escape(str) {
|
||||
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
},
|
||||
};
|
||||
|
||||
// --- Navigation ---
|
||||
|
||||
function navigate(topicId) {
|
||||
state.activeTopic = topicId;
|
||||
state.expandedGroup = findParentGroup(topicId);
|
||||
renderSidebar();
|
||||
loadTopic(topicId);
|
||||
}
|
||||
|
||||
// --- Init ---
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
try {
|
||||
const resp = await fetch("data/topics.json");
|
||||
state.topics = await resp.json();
|
||||
|
||||
const hash = location.hash.slice(1);
|
||||
state.activeTopic = state.topics.find((t) => t.id === hash) ? hash : state.topics[0].id;
|
||||
state.expandedGroup = findParentGroup(state.activeTopic);
|
||||
|
||||
renderSidebar();
|
||||
await loadTopic(state.activeTopic);
|
||||
} catch (e) {
|
||||
dom.content().innerHTML = `<p style="color:var(--artery-text);">Failed to load topics: ${e.message}</p>`;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("hashchange", () => {
|
||||
const hash = location.hash.slice(1);
|
||||
if (state.topics.find((t) => t.id === hash) && hash !== state.activeTopic) {
|
||||
navigate(hash);
|
||||
}
|
||||
});
|
||||
45
docs/graphs/artery_hierarchy.dot
Normal file
@@ -0,0 +1,45 @@
|
||||
digraph artery_hierarchy {
|
||||
bgcolor="#0a0a0a"
|
||||
rankdir=LR
|
||||
fontname="Helvetica"
|
||||
node [fontname="Helvetica" fontsize=11 style=filled color="#333" fontcolor="#e5e5e5" shape=box]
|
||||
edge [fontname="Helvetica" fontsize=9 fontcolor="#a3a3a3" color="#b91c1c"]
|
||||
|
||||
label="Artery — Component Hierarchy"
|
||||
labelloc=t
|
||||
fontsize=14
|
||||
fontcolor="#fca5a5"
|
||||
|
||||
vein [label="Vein\nstateless API connector" fillcolor="#1a1a1a"]
|
||||
pulse [label="Pulse\nVein + Room + Depot" fillcolor="#1a1a1a"]
|
||||
plexus [label="Plexus\nfull app: backend\n+ frontend + DB" fillcolor="#1a1a1a"]
|
||||
shunt [label="Shunt\nfake connector\nfor testing" fillcolor="#1a1a1a" color="#d4a574"]
|
||||
|
||||
vein -> pulse [label="compose"]
|
||||
pulse -> plexus [label="extend"]
|
||||
shunt -> vein [label="replaces" style=dashed color="#d4a574" fontcolor="#d4a574"]
|
||||
|
||||
// Examples
|
||||
subgraph cluster_examples {
|
||||
label="Live Veins"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
jira [label="Jira" fillcolor="#1a1a1a" fontcolor="#15803d" fontsize=9]
|
||||
google [label="Google" fillcolor="#1a1a1a" fontcolor="#d4a574" fontsize=9]
|
||||
ia [label="IA" fillcolor="#1a1a1a" fontcolor="#15803d" fontsize=9]
|
||||
}
|
||||
|
||||
subgraph cluster_shunts {
|
||||
label="Shunts"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
mp [label="MercadoPago" fillcolor="#1a1a1a" fontcolor="#d4a574" fontsize=9]
|
||||
}
|
||||
|
||||
jira -> vein [style=invis]
|
||||
mp -> shunt [style=invis]
|
||||
}
|
||||
101
docs/graphs/artery_hierarchy.svg
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: artery_hierarchy Pages: 1 -->
|
||||
<svg width="845pt" height="317pt"
|
||||
viewBox="0.00 0.00 845.00 317.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 313.25)">
|
||||
<title>artery_hierarchy</title>
|
||||
<polygon fill="#0a0a0a" stroke="none" points="-4,4 -4,-313.25 840.5,-313.25 840.5,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="418.25" y="-291.95" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#fca5a5">Artery — Component Hierarchy</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_examples</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="135.88,-8 135.88,-193 220.88,-193 220.88,-8 135.88,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="178.38" y="-175.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">Live Veins</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_shunts</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="8,-199 8,-276 100,-276 100,-199 8,-199"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="54" y="-258.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">Shunts</text>
|
||||
</g>
|
||||
<!-- vein -->
|
||||
<g id="node1" class="node">
|
||||
<title>vein</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="446,-167 300.25,-167 300.25,-131 446,-131 446,-167"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="373.12" y="-152.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Vein</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="373.12" y="-138.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">stateless API connector</text>
|
||||
</g>
|
||||
<!-- pulse -->
|
||||
<g id="node2" class="node">
|
||||
<title>pulse</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="659.25,-167 522.5,-167 522.5,-131 659.25,-131 659.25,-167"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="590.88" y="-152.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Pulse</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="590.88" y="-138.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Vein + Room + Depot</text>
|
||||
</g>
|
||||
<!-- vein->pulse -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>vein->pulse</title>
|
||||
<path fill="none" stroke="#b91c1c" d="M446.27,-149C467.03,-149 489.79,-149 510.95,-149"/>
|
||||
<polygon fill="#b91c1c" stroke="#b91c1c" points="510.67,-152.5 520.67,-149 510.67,-145.5 510.67,-152.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="484.25" y="-151.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">compose</text>
|
||||
</g>
|
||||
<!-- plexus -->
|
||||
<g id="node3" class="node">
|
||||
<title>plexus</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="836.5,-173.25 726.75,-173.25 726.75,-124.75 836.5,-124.75 836.5,-173.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="781.62" y="-158.8" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Plexus</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="781.62" y="-145.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">full app: backend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="781.62" y="-131.8" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">+ frontend + DB</text>
|
||||
</g>
|
||||
<!-- pulse->plexus -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>pulse->plexus</title>
|
||||
<path fill="none" stroke="#b91c1c" d="M659.48,-149C677.62,-149 697.19,-149 715.21,-149"/>
|
||||
<polygon fill="#b91c1c" stroke="#b91c1c" points="714.98,-152.5 724.98,-149 714.98,-145.5 714.98,-152.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="693" y="-151.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">extend</text>
|
||||
</g>
|
||||
<!-- shunt -->
|
||||
<g id="node4" class="node">
|
||||
<title>shunt</title>
|
||||
<polygon fill="#1a1a1a" stroke="#d4a574" points="226.75,-249.25 129,-249.25 129,-200.75 226.75,-200.75 226.75,-249.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="177.88" y="-234.8" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Shunt</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="177.88" y="-221.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">fake connector</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="177.88" y="-207.8" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">for testing</text>
|
||||
</g>
|
||||
<!-- shunt->vein -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>shunt->vein</title>
|
||||
<path fill="none" stroke="#d4a574" stroke-dasharray="5,2" d="M227.14,-206.02C253.71,-195.57 286.85,-182.54 314.73,-171.57"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="315.71,-174.95 323.73,-168.03 313.14,-168.43 315.71,-174.95"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="263.5" y="-200.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#d4a574">replaces</text>
|
||||
</g>
|
||||
<!-- jira -->
|
||||
<g id="node5" class="node">
|
||||
<title>jira</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="204.88,-52 150.88,-52 150.88,-16 204.88,-16 204.88,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="177.88" y="-31.07" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#15803d">Jira</text>
|
||||
</g>
|
||||
<!-- jira->vein -->
|
||||
<!-- google -->
|
||||
<g id="node6" class="node">
|
||||
<title>google</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="204.88,-106 150.88,-106 150.88,-70 204.88,-70 204.88,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="177.88" y="-85.08" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#d4a574">Google</text>
|
||||
</g>
|
||||
<!-- ia -->
|
||||
<g id="node7" class="node">
|
||||
<title>ia</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="204.88,-160 150.88,-160 150.88,-124 204.88,-124 204.88,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="177.88" y="-139.07" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#15803d">IA</text>
|
||||
</g>
|
||||
<!-- mp -->
|
||||
<g id="node8" class="node">
|
||||
<title>mp</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="92,-243 16,-243 16,-207 92,-207 92,-243"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="54" y="-222.07" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#d4a574">MercadoPago</text>
|
||||
</g>
|
||||
<!-- mp->shunt -->
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
49
docs/graphs/cfg_gen_flow.dot
Normal file
@@ -0,0 +1,49 @@
|
||||
digraph cfg_gen_flow {
|
||||
bgcolor="#0a0a0a"
|
||||
rankdir=LR
|
||||
fontname="Helvetica"
|
||||
node [fontname="Helvetica" fontsize=11 style=filled color="#333" fontcolor="#e5e5e5" shape=box]
|
||||
edge [fontname="Helvetica" fontsize=9 fontcolor="#a3a3a3" color="#d4a574"]
|
||||
|
||||
label="Build Flow — cfg/ to gen/"
|
||||
labelloc=t
|
||||
fontsize=14
|
||||
fontcolor="#d4a574"
|
||||
|
||||
// Source
|
||||
subgraph cluster_source {
|
||||
label="Source (committed)"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
core [label="soleprint/\ncore framework" fillcolor="#1a1a1a"]
|
||||
cfg [label="cfg/<room>/\nroom config" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
// Build
|
||||
build [label="build.py\n--cfg <room>" fillcolor="#1a1a1a" color="#d4a574" shape=component]
|
||||
|
||||
// Output
|
||||
subgraph cluster_output {
|
||||
label="Output (generated, gitignored)"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
gen_spr [label="gen/<room>/soleprint/\ncore + room merged" fillcolor="#1a1a1a"]
|
||||
gen_app [label="gen/<room>/<app>/\ncloned repos" fillcolor="#1a1a1a"]
|
||||
gen_link [label="gen/<room>/link/\nDB bridge" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
// Run
|
||||
docker [label="docker compose up" fillcolor="#1a1a1a" shape=component]
|
||||
|
||||
// Flow
|
||||
core -> build
|
||||
cfg -> build
|
||||
build -> gen_spr
|
||||
build -> gen_app [style=dashed label="if managed"]
|
||||
build -> gen_link [style=dashed label="if managed"]
|
||||
gen_spr -> docker
|
||||
}
|
||||
114
docs/graphs/cfg_gen_flow.svg
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: cfg_gen_flow Pages: 1 -->
|
||||
<svg width="742pt" height="234pt"
|
||||
viewBox="0.00 0.00 742.00 234.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 230.25)">
|
||||
<title>cfg_gen_flow</title>
|
||||
<polygon fill="#0a0a0a" stroke="none" points="-4,4 -4,-230.25 737.5,-230.25 737.5,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="366.75" y="-208.95" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Build Flow — cfg/ to gen/</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_source</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="0,-62 0,-193 152.5,-193 152.5,-62 0,-62"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="76.25" y="-175.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">Source (committed)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_output</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="350.75,-8 350.75,-193 581.25,-193 581.25,-8 350.75,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="466" y="-175.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">Output (generated, gitignored)</text>
|
||||
</g>
|
||||
<!-- core -->
|
||||
<g id="node1" class="node">
|
||||
<title>core</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="126.88,-160 24.63,-160 24.63,-124 126.88,-124 126.88,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="75.75" y="-145.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">soleprint/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="75.75" y="-131.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">core framework</text>
|
||||
</g>
|
||||
<!-- build -->
|
||||
<g id="node3" class="node">
|
||||
<title>build</title>
|
||||
<polygon fill="#1a1a1a" stroke="#d4a574" points="271.75,-106 181.5,-106 181.5,-102 177.5,-102 177.5,-98 181.5,-98 181.5,-78 177.5,-78 177.5,-74 181.5,-74 181.5,-70 271.75,-70 271.75,-106"/>
|
||||
<polyline fill="none" stroke="#d4a574" points="181.5,-102 185.5,-102 185.5,-98 181.5,-98"/>
|
||||
<polyline fill="none" stroke="#d4a574" points="181.5,-78 185.5,-78 185.5,-74 181.5,-74"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="226.62" y="-91.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">build.py</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="226.62" y="-77.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">--cfg <room></text>
|
||||
</g>
|
||||
<!-- core->build -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>core->build</title>
|
||||
<path fill="none" stroke="#d4a574" d="M127.3,-124.07C135.72,-121.06 144.36,-117.95 152.5,-115 158.3,-112.89 164.36,-110.68 170.4,-108.47"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="171.59,-111.76 179.76,-105.02 169.17,-105.19 171.59,-111.76"/>
|
||||
</g>
|
||||
<!-- cfg -->
|
||||
<g id="node2" class="node">
|
||||
<title>cfg</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="119,-106 32.5,-106 32.5,-70 119,-70 119,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="75.75" y="-91.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">cfg/<room>/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="75.75" y="-77.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">room config</text>
|
||||
</g>
|
||||
<!-- cfg->build -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>cfg->build</title>
|
||||
<path fill="none" stroke="#d4a574" d="M119.41,-88C135.12,-88 153.15,-88 169.84,-88"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="169.63,-91.5 179.63,-88 169.63,-84.5 169.63,-91.5"/>
|
||||
</g>
|
||||
<!-- gen_spr -->
|
||||
<g id="node4" class="node">
|
||||
<title>gen_spr</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="536.5,-160 394.5,-160 394.5,-124 536.5,-124 536.5,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="465.5" y="-145.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">gen/<room>/soleprint/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="465.5" y="-131.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">core + room merged</text>
|
||||
</g>
|
||||
<!-- build->gen_spr -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>build->gen_spr</title>
|
||||
<path fill="none" stroke="#d4a574" d="M272.06,-98.83C278,-100.25 284.02,-101.67 289.75,-103 320.22,-110.08 353.74,-117.62 383.21,-124.16"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="382.29,-127.55 392.81,-126.29 383.8,-120.71 382.29,-127.55"/>
|
||||
</g>
|
||||
<!-- gen_app -->
|
||||
<g id="node5" class="node">
|
||||
<title>gen_app</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="531.62,-106 399.38,-106 399.38,-70 531.62,-70 531.62,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="465.5" y="-91.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">gen/<room>/<app>/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="465.5" y="-77.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">cloned repos</text>
|
||||
</g>
|
||||
<!-- build->gen_app -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>build->gen_app</title>
|
||||
<path fill="none" stroke="#d4a574" stroke-dasharray="5,2" d="M272.18,-88C304.75,-88 349.72,-88 388,-88"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="387.6,-91.5 397.6,-88 387.6,-84.5 387.6,-91.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="315.25" y="-90.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">if managed</text>
|
||||
</g>
|
||||
<!-- gen_link -->
|
||||
<g id="node6" class="node">
|
||||
<title>gen_link</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="521.88,-52 409.12,-52 409.12,-16 521.88,-16 521.88,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="465.5" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">gen/<room>/link/</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="465.5" y="-23.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">DB bridge</text>
|
||||
</g>
|
||||
<!-- build->gen_link -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>build->gen_link</title>
|
||||
<path fill="none" stroke="#d4a574" stroke-dasharray="5,2" d="M272.05,-76.97C278,-75.53 284.02,-74.09 289.75,-72.75 325.35,-64.44 365.13,-55.58 397.73,-48.44"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="398.44,-51.86 407.46,-46.31 396.95,-45.03 398.44,-51.86"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="315.25" y="-75.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">if managed</text>
|
||||
</g>
|
||||
<!-- docker -->
|
||||
<g id="node7" class="node">
|
||||
<title>docker</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="733.5,-160 610.25,-160 610.25,-156 606.25,-156 606.25,-152 610.25,-152 610.25,-132 606.25,-132 606.25,-128 610.25,-128 610.25,-124 733.5,-124 733.5,-160"/>
|
||||
<polyline fill="none" stroke="#333333" points="610.25,-156 614.25,-156 614.25,-152 610.25,-152"/>
|
||||
<polyline fill="none" stroke="#333333" points="610.25,-132 614.25,-132 614.25,-128 610.25,-128"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="671.88" y="-138.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">docker compose up</text>
|
||||
</g>
|
||||
<!-- gen_spr->docker -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>gen_spr->docker</title>
|
||||
<path fill="none" stroke="#d4a574" d="M536.83,-142C556.81,-142 578.59,-142 598.68,-142"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="598.44,-145.5 608.44,-142 598.44,-138.5 598.44,-145.5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
31
docs/graphs/room_layers.dot
Normal file
@@ -0,0 +1,31 @@
|
||||
digraph room_layers {
|
||||
bgcolor="#0a0a0a"
|
||||
rankdir=TB
|
||||
fontname="Helvetica"
|
||||
node [fontname="Helvetica" fontsize=10 style=filled color="#333" fontcolor="#e5e5e5" shape=record]
|
||||
edge [fontname="Helvetica" fontsize=9 fontcolor="#a3a3a3" color="#666"]
|
||||
|
||||
label="Room Layers — init wizard"
|
||||
labelloc=t
|
||||
fontsize=14
|
||||
fontcolor="#d4a574"
|
||||
|
||||
l0 [label="{Layer 0 | Config + Data | config.json · data/*.json}" fillcolor="#1a1a1a" color="#d4a574"]
|
||||
l1 [label="{Layer 1 | Docker | soleprint/docker-compose.yml · .env}" fillcolor="#1a1a1a"]
|
||||
l2 [label="{Layer 2 | Managed App | docker-compose.yml · Dockerfiles · .env}" fillcolor="#1a1a1a"]
|
||||
l3 [label="{Layer 3 | Link | link/main.py · adapters/ · Dockerfile}" fillcolor="#1a1a1a"]
|
||||
l4 [label="{Layer 4 | Scripts | ctrl/start.sh · stop.sh · status.sh · logs.sh}" fillcolor="#1a1a1a"]
|
||||
l5 [label="{Layer 5 | Systems | tester/environments.json · tests/}" fillcolor="#1a1a1a"]
|
||||
l6 [label="{Layer 6 | Nginx | nginx/local.conf · docker-compose.nginx.yml}" fillcolor="#1a1a1a"]
|
||||
|
||||
l0 -> l1 [label="required"]
|
||||
l1 -> l2 [label="if managed"]
|
||||
l2 -> l3 [label="optional"]
|
||||
l1 -> l4 [label="optional"]
|
||||
l4 -> l5 [label="optional"]
|
||||
l5 -> l6 [label="if frontend"]
|
||||
|
||||
// Annotations
|
||||
note_req [label="every room" fillcolor="#0a0a0a" fontcolor="#d4a574" color="#0a0a0a" shape=plaintext fontsize=9]
|
||||
note_req -> l0 [style=invis]
|
||||
}
|
||||
133
docs/graphs/room_layers.svg
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: room_layers Pages: 1 -->
|
||||
<svg width="461pt" height="612pt"
|
||||
viewBox="0.00 0.00 461.00 612.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 607.5)">
|
||||
<title>room_layers</title>
|
||||
<polygon fill="#0a0a0a" stroke="none" points="-4,4 -4,-607.5 456.62,-607.5 456.62,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="226.31" y="-586.2" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Room Layers — init wizard</text>
|
||||
<!-- l0 -->
|
||||
<g id="node1" class="node">
|
||||
<title>l0</title>
|
||||
<polygon fill="#1a1a1a" stroke="#d4a574" points="155.12,-442.5 155.12,-504.75 285.88,-504.75 285.88,-442.5 155.12,-442.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-491.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 0</text>
|
||||
<polyline fill="none" stroke="#d4a574" points="155.12,-484 285.88,-484"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-470.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Config + Data</text>
|
||||
<polyline fill="none" stroke="#d4a574" points="155.12,-463.25 285.88,-463.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-449.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">config.json · data/*.json</text>
|
||||
</g>
|
||||
<!-- l1 -->
|
||||
<g id="node2" class="node">
|
||||
<title>l1</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="123.62,-332 123.62,-394.25 317.38,-394.25 317.38,-332 123.62,-332"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-380.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 1</text>
|
||||
<polyline fill="none" stroke="#333333" points="123.62,-373.5 317.38,-373.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-360" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Docker</text>
|
||||
<polyline fill="none" stroke="#333333" points="123.62,-352.75 317.38,-352.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-339.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">soleprint/docker-compose.yml · .env</text>
|
||||
</g>
|
||||
<!-- l0->l1 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>l0->l1</title>
|
||||
<path fill="none" stroke="#666666" d="M220.5,-442.11C220.5,-430.81 220.5,-417.79 220.5,-405.67"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="224,-405.92 220.5,-395.92 217,-405.92 224,-405.92"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239.62" y="-415.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">required</text>
|
||||
</g>
|
||||
<!-- l2 -->
|
||||
<g id="node3" class="node">
|
||||
<title>l2</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="0,-221.5 0,-283.75 211,-283.75 211,-221.5 0,-221.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="105.5" y="-270.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 2</text>
|
||||
<polyline fill="none" stroke="#333333" points="0,-263 211,-263"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="105.5" y="-249.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Managed App</text>
|
||||
<polyline fill="none" stroke="#333333" points="0,-242.25 211,-242.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="105.5" y="-228.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">docker-compose.yml · Dockerfiles · .env</text>
|
||||
</g>
|
||||
<!-- l1->l2 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>l1->l2</title>
|
||||
<path fill="none" stroke="#666666" d="M188.16,-331.61C174.94,-319.14 159.52,-304.59 145.59,-291.45"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="148.37,-289.26 138.7,-284.95 143.57,-294.36 148.37,-289.26"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="191.95" y="-304.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">if managed</text>
|
||||
</g>
|
||||
<!-- l4 -->
|
||||
<g id="node5" class="node">
|
||||
<title>l4</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="229.25,-221.5 229.25,-283.75 441.75,-283.75 441.75,-221.5 229.25,-221.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-270.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 4</text>
|
||||
<polyline fill="none" stroke="#333333" points="229.25,-263 441.75,-263"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-249.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Scripts</text>
|
||||
<polyline fill="none" stroke="#333333" points="229.25,-242.25 441.75,-242.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-228.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">ctrl/start.sh · stop.sh · status.sh · logs.sh</text>
|
||||
</g>
|
||||
<!-- l1->l4 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>l1->l4</title>
|
||||
<path fill="none" stroke="#666666" d="M252.84,-331.61C266.06,-319.14 281.48,-304.59 295.41,-291.45"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="297.43,-294.36 302.3,-284.95 292.63,-289.26 297.43,-294.36"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="299.45" y="-304.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">optional</text>
|
||||
</g>
|
||||
<!-- l3 -->
|
||||
<g id="node4" class="node">
|
||||
<title>l3</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="10.88,-111 10.88,-173.25 200.12,-173.25 200.12,-111 10.88,-111"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="105.5" y="-159.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 3</text>
|
||||
<polyline fill="none" stroke="#333333" points="10.88,-152.5 200.12,-152.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="105.5" y="-139" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Link</text>
|
||||
<polyline fill="none" stroke="#333333" points="10.88,-131.75 200.12,-131.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="105.5" y="-118.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">link/main.py · adapters/ · Dockerfile</text>
|
||||
</g>
|
||||
<!-- l2->l3 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>l2->l3</title>
|
||||
<path fill="none" stroke="#666666" d="M105.5,-221.11C105.5,-209.81 105.5,-196.79 105.5,-184.67"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="109,-184.92 105.5,-174.92 102,-184.92 109,-184.92"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="123.5" y="-194.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">optional</text>
|
||||
</g>
|
||||
<!-- l5 -->
|
||||
<g id="node6" class="node">
|
||||
<title>l5</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="248.38,-111 248.38,-173.25 422.62,-173.25 422.62,-111 248.38,-111"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-159.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 5</text>
|
||||
<polyline fill="none" stroke="#333333" points="248.38,-152.5 422.62,-152.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-139" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Systems</text>
|
||||
<polyline fill="none" stroke="#333333" points="248.38,-131.75 422.62,-131.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-118.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">tester/environments.json · tests/</text>
|
||||
</g>
|
||||
<!-- l4->l5 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>l4->l5</title>
|
||||
<path fill="none" stroke="#666666" d="M335.5,-221.11C335.5,-209.81 335.5,-196.79 335.5,-184.67"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="339,-184.92 335.5,-174.92 332,-184.92 339,-184.92"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="353.5" y="-194.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">optional</text>
|
||||
</g>
|
||||
<!-- l6 -->
|
||||
<g id="node7" class="node">
|
||||
<title>l6</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="218.38,-0.5 218.38,-62.75 452.62,-62.75 452.62,-0.5 218.38,-0.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-49.25" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Layer 6</text>
|
||||
<polyline fill="none" stroke="#333333" points="218.38,-42 452.62,-42"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-28.5" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">Nginx</text>
|
||||
<polyline fill="none" stroke="#333333" points="218.38,-21.25 452.62,-21.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="335.5" y="-7.75" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#e5e5e5">nginx/local.conf · docker-compose.nginx.yml</text>
|
||||
</g>
|
||||
<!-- l5->l6 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>l5->l6</title>
|
||||
<path fill="none" stroke="#666666" d="M335.5,-110.61C335.5,-99.31 335.5,-86.29 335.5,-74.17"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="339,-74.42 335.5,-64.42 332,-74.42 339,-74.42"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="359.12" y="-83.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">if frontend</text>
|
||||
</g>
|
||||
<!-- note_req -->
|
||||
<g id="node8" class="node">
|
||||
<title>note_req</title>
|
||||
<polygon fill="#0a0a0a" stroke="none" points="254,-578.25 187,-578.25 187,-542.25 254,-542.25 254,-578.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="220.5" y="-557.33" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#d4a574">every room</text>
|
||||
</g>
|
||||
<!-- note_req->l0 -->
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.3 KiB |
97
docs/graphs/system_overview.dot
Normal file
@@ -0,0 +1,97 @@
|
||||
digraph system_overview {
|
||||
bgcolor="#0a0a0a"
|
||||
rankdir=TB
|
||||
compound=true
|
||||
fontname="Helvetica"
|
||||
node [fontname="Helvetica" fontsize=11 style=filled color="#333" fontcolor="#e5e5e5"]
|
||||
edge [fontname="Helvetica" fontsize=9 fontcolor="#a3a3a3" color="#666"]
|
||||
|
||||
label="Soleprint — System Overview"
|
||||
labelloc=t
|
||||
fontsize=14
|
||||
fontcolor="#d4a574"
|
||||
|
||||
// Core
|
||||
subgraph cluster_core {
|
||||
label="Soleprint Hub"
|
||||
style=dashed
|
||||
color="#d4a574"
|
||||
fontcolor="#d4a574"
|
||||
|
||||
hub [label="soleprint\ncore coordinator\nport 12000" fillcolor="#1a1a1a" shape=box]
|
||||
}
|
||||
|
||||
// Artery
|
||||
subgraph cluster_artery {
|
||||
label="Artery — Todo lo vital"
|
||||
style=dashed
|
||||
color="#b91c1c"
|
||||
fontcolor="#fca5a5"
|
||||
|
||||
veins [label="Veins\nstateless connectors" fillcolor="#1a1a1a"]
|
||||
shunts [label="Shunts\nmock connectors" fillcolor="#1a1a1a"]
|
||||
pulses [label="Pulses\ncomposed flows" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
// Atlas
|
||||
subgraph cluster_atlas {
|
||||
label="Atlas — Documentacion accionable"
|
||||
style=dashed
|
||||
color="#15803d"
|
||||
fontcolor="#86efac"
|
||||
|
||||
books [label="Books\ndocumentation" fillcolor="#1a1a1a"]
|
||||
templates [label="Templates\npatterns" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
// Station
|
||||
subgraph cluster_station {
|
||||
label="Station — Centro de control"
|
||||
style=dashed
|
||||
color="#1d4ed8"
|
||||
fontcolor="#93c5fd"
|
||||
|
||||
tools [label="Tools\ntester · datagen · modelgen" fillcolor="#1a1a1a"]
|
||||
monitors [label="Monitors\ndatabrowse" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
// External
|
||||
subgraph cluster_external {
|
||||
label="External APIs"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
jira [label="Jira" fillcolor="#1a1a1a" fontcolor="#a3a3a3"]
|
||||
google [label="Google" fillcolor="#1a1a1a" fontcolor="#a3a3a3"]
|
||||
slack [label="Slack" fillcolor="#1a1a1a" fontcolor="#a3a3a3"]
|
||||
}
|
||||
|
||||
// Managed app
|
||||
subgraph cluster_managed {
|
||||
label="Managed App"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
app_fe [label="Frontend" fillcolor="#1a1a1a" fontcolor="#a3a3a3"]
|
||||
app_be [label="Backend" fillcolor="#1a1a1a" fontcolor="#a3a3a3"]
|
||||
app_db [label="Database" fillcolor="#1a1a1a" fontcolor="#a3a3a3" shape=cylinder]
|
||||
}
|
||||
|
||||
// Connections
|
||||
hub -> veins [label="routes" color="#b91c1c"]
|
||||
hub -> books [label="routes" color="#15803d"]
|
||||
hub -> tools [label="routes" color="#1d4ed8"]
|
||||
|
||||
veins -> jira [label="API"]
|
||||
veins -> google [label="OAuth"]
|
||||
veins -> slack [label="API"]
|
||||
veins -> pulses [label="compose"]
|
||||
|
||||
tools -> app_be [label="test" style=dashed]
|
||||
monitors -> app_db [label="browse" style=dashed]
|
||||
|
||||
// Sidebar injection
|
||||
hub -> app_fe [label="sidebar\ninjection" color="#d4a574" style=dashed]
|
||||
}
|
||||
209
docs/graphs/system_overview.svg
Normal file
@@ -0,0 +1,209 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: system_overview Pages: 1 -->
|
||||
<svg width="1153pt" height="372pt"
|
||||
viewBox="0.00 0.00 1153.00 372.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 368.25)">
|
||||
<title>system_overview</title>
|
||||
<polygon fill="#0a0a0a" stroke="none" points="-4,4 -4,-368.25 1149,-368.25 1149,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="572.5" y="-346.95" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Soleprint — System Overview</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_core</title>
|
||||
<polygon fill="#0a0a0a" stroke="#d4a574" stroke-dasharray="5,2" points="538,-241.25 538,-331 660,-331 660,-241.25 538,-241.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="599" y="-313.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Soleprint Hub</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_artery</title>
|
||||
<polygon fill="#0a0a0a" stroke="#b91c1c" stroke-dasharray="5,2" points="8,-8 8,-212 382,-212 382,-8 8,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="195" y="-194.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#fca5a5">Artery — Todo lo vital</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_atlas</title>
|
||||
<polygon fill="#0a0a0a" stroke="#15803d" stroke-dasharray="5,2" points="390,-121.25 390,-212 665,-212 665,-121.25 390,-121.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="527.5" y="-194.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#86efac">Atlas — Documentacion accionable</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_station</title>
|
||||
<polygon fill="#0a0a0a" stroke="#1d4ed8" stroke-dasharray="5,2" points="673,-121.25 673,-212 1062,-212 1062,-121.25 673,-121.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="867.5" y="-194.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#93c5fd">Station — Centro de control</text>
|
||||
</g>
|
||||
<g id="clust5" class="cluster">
|
||||
<title>cluster_external</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="390,-14.75 390,-92 620,-92 620,-14.75 390,-14.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="505" y="-74.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">External APIs</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_managed</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="859,-14.75 859,-92 1137,-92 1137,-14.75 859,-14.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="998" y="-74.7" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">Managed App</text>
|
||||
</g>
|
||||
<!-- hub -->
|
||||
<g id="node1" class="node">
|
||||
<title>hub</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="652.38,-297.75 545.62,-297.75 545.62,-249.25 652.38,-249.25 652.38,-297.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="599" y="-283.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">soleprint</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="599" y="-269.8" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">core coordinator</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="599" y="-256.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">port 12000</text>
|
||||
</g>
|
||||
<!-- veins -->
|
||||
<g id="node2" class="node">
|
||||
<title>veins</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="108" cy="-154" rx="92.45" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="108" y="-157.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Veins</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="108" y="-143.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">stateless connectors</text>
|
||||
</g>
|
||||
<!-- hub->veins -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>hub->veins</title>
|
||||
<path fill="none" stroke="#b91c1c" d="M545.18,-270.24C468.57,-265.68 324.55,-252.07 209,-212 188.62,-204.93 167.6,-193.79 150.05,-183.23"/>
|
||||
<polygon fill="#b91c1c" stroke="#b91c1c" points="152.32,-180.52 141.98,-178.24 148.65,-186.47 152.32,-180.52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="284.95" y="-222.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">routes</text>
|
||||
</g>
|
||||
<!-- books -->
|
||||
<g id="node5" class="node">
|
||||
<title>books</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="468" cy="-154" rx="69.65" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="468" y="-157.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Books</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="468" y="-143.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">documentation</text>
|
||||
</g>
|
||||
<!-- hub->books -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>hub->books</title>
|
||||
<path fill="none" stroke="#15803d" d="M572.81,-249C552.24,-230.55 523.47,-204.75 501.27,-184.84"/>
|
||||
<polygon fill="#15803d" stroke="#15803d" points="503.73,-182.34 493.94,-178.27 499.05,-187.55 503.73,-182.34"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="567.14" y="-222.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">routes</text>
|
||||
</g>
|
||||
<!-- tools -->
|
||||
<g id="node7" class="node">
|
||||
<title>tools</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="802" cy="-154" rx="120.56" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="802" y="-157.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Tools</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="802" y="-143.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">tester · datagen · modelgen</text>
|
||||
</g>
|
||||
<!-- hub->tools -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>hub->tools</title>
|
||||
<path fill="none" stroke="#1d4ed8" d="M639.59,-249C672.13,-230.17 717.93,-203.66 752.6,-183.59"/>
|
||||
<polygon fill="#1d4ed8" stroke="#1d4ed8" points="754.3,-186.65 761.2,-178.61 750.8,-180.59 754.3,-186.65"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="702.6" y="-222.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">routes</text>
|
||||
</g>
|
||||
<!-- app_fe -->
|
||||
<g id="node12" class="node">
|
||||
<title>app_fe</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="1089" cy="-40.75" rx="39.9" ry="18"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1089" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#a3a3a3">Frontend</text>
|
||||
</g>
|
||||
<!-- hub->app_fe -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>hub->app_fe</title>
|
||||
<path fill="none" stroke="#d4a574" stroke-dasharray="5,2" d="M652.46,-273.38C762.51,-274.01 1008.83,-268.85 1066,-212 1103.21,-174.99 1100.13,-108.42 1094.57,-70.42"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="1098.04,-69.95 1092.97,-60.65 1091.14,-71.08 1098.04,-69.95"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1116.94" y="-156.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">sidebar</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1116.94" y="-145.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">injection</text>
|
||||
</g>
|
||||
<!-- pulses -->
|
||||
<g id="node4" class="node">
|
||||
<title>pulses</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="108" cy="-40.75" rx="73.89" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="108" y="-43.8" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Pulses</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="108" y="-30.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">composed flows</text>
|
||||
</g>
|
||||
<!-- veins->pulses -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>veins->pulses</title>
|
||||
<path fill="none" stroke="#666666" d="M108,-128.86C108,-113.7 108,-93.88 108,-76.98"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="111.5,-77.35 108,-67.35 104.5,-77.35 111.5,-77.35"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="128.25" y="-102.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">compose</text>
|
||||
</g>
|
||||
<!-- jira -->
|
||||
<g id="node9" class="node">
|
||||
<title>jira</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="425" cy="-40.75" rx="27" ry="18"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="425" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#a3a3a3">Jira</text>
|
||||
</g>
|
||||
<!-- veins->jira -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>veins->jira</title>
|
||||
<path fill="none" stroke="#666666" d="M163.97,-133.86C178.52,-129.32 194.25,-124.77 209,-121.25 286.56,-102.75 317.5,-132.81 386,-92 395.89,-86.1 404.2,-76.67 410.57,-67.57"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="413.44,-69.58 415.88,-59.27 407.54,-65.8 413.44,-69.58"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="377.36" y="-102.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">API</text>
|
||||
</g>
|
||||
<!-- google -->
|
||||
<g id="node10" class="node">
|
||||
<title>google</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="504" cy="-40.75" rx="33.82" ry="18"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="504" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#a3a3a3">Google</text>
|
||||
</g>
|
||||
<!-- veins->google -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>veins->google</title>
|
||||
<path fill="none" stroke="#666666" d="M161.63,-133.42C176.76,-128.65 193.36,-124.1 209,-121.25 287.39,-106.97 309.3,-123.69 388,-111.25 421.14,-106.01 432.58,-109.83 461,-92 471.11,-85.66 480.09,-76.19 487.2,-67.17"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="489.88,-69.43 493,-59.31 484.25,-65.28 489.88,-69.43"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="459.93" y="-102.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">OAuth</text>
|
||||
</g>
|
||||
<!-- slack -->
|
||||
<g id="node11" class="node">
|
||||
<title>slack</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="584" cy="-40.75" rx="27.74" ry="18"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="584" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#a3a3a3">Slack</text>
|
||||
</g>
|
||||
<!-- veins->slack -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>veins->slack</title>
|
||||
<path fill="none" stroke="#666666" d="M161.07,-133.39C176.34,-128.56 193.15,-123.98 209,-121.25 326.9,-100.91 359.79,-129.67 478,-111.25 509.46,-106.35 520.8,-110.08 547,-92 556.07,-85.74 563.77,-76.52 569.76,-67.68"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="572.65,-69.66 574.98,-59.33 566.72,-65.96 572.65,-69.66"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="539.91" y="-102.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">API</text>
|
||||
</g>
|
||||
<!-- shunts -->
|
||||
<g id="node3" class="node">
|
||||
<title>shunts</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="296" cy="-154" rx="77.6" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="296" y="-157.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Shunts</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="296" y="-143.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">mock connectors</text>
|
||||
</g>
|
||||
<!-- templates -->
|
||||
<g id="node6" class="node">
|
||||
<title>templates</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="606" cy="-154" rx="50.56" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="606" y="-157.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Templates</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="606" y="-143.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">patterns</text>
|
||||
</g>
|
||||
<!-- app_be -->
|
||||
<g id="node13" class="node">
|
||||
<title>app_be</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="906" cy="-40.75" rx="38.96" ry="18"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="906" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#a3a3a3">Backend</text>
|
||||
</g>
|
||||
<!-- tools->app_be -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>tools->app_be</title>
|
||||
<path fill="none" stroke="#666666" stroke-dasharray="5,2" d="M824.06,-129.4C841.45,-110.79 865.64,-84.93 883.22,-66.12"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="885.72,-68.57 889.99,-58.88 880.6,-63.79 885.72,-68.57"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="859.51" y="-102.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">test</text>
|
||||
</g>
|
||||
<!-- monitors -->
|
||||
<g id="node8" class="node">
|
||||
<title>monitors</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="997" cy="-154" rx="56.92" ry="24.75"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="997" y="-157.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Monitors</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="997" y="-143.55" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">databrowse</text>
|
||||
</g>
|
||||
<!-- app_db -->
|
||||
<g id="node14" class="node">
|
||||
<title>app_db</title>
|
||||
<path fill="#1a1a1a" stroke="#333333" d="M1031.25,-55.48C1031.25,-57.28 1015.9,-58.75 997,-58.75 978.1,-58.75 962.75,-57.28 962.75,-55.48 962.75,-55.48 962.75,-26.02 962.75,-26.02 962.75,-24.22 978.1,-22.75 997,-22.75 1015.9,-22.75 1031.25,-24.22 1031.25,-26.02 1031.25,-26.02 1031.25,-55.48 1031.25,-55.48"/>
|
||||
<path fill="none" stroke="#333333" d="M1031.25,-55.48C1031.25,-53.67 1015.9,-52.2 997,-52.2 978.1,-52.2 962.75,-53.67 962.75,-55.48"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="997" y="-37.05" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#a3a3a3">Database</text>
|
||||
</g>
|
||||
<!-- monitors->app_db -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>monitors->app_db</title>
|
||||
<path fill="none" stroke="#666666" stroke-dasharray="5,2" d="M997,-128.86C997,-111.64 997,-88.42 997,-70.29"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="1000.5,-70.46 997,-60.46 993.5,-70.46 1000.5,-70.46"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1013.12" y="-102.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">browse</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
54
docs/graphs/wrapping.dot
Normal file
@@ -0,0 +1,54 @@
|
||||
digraph wrapping {
|
||||
bgcolor="#0a0a0a"
|
||||
rankdir=LR
|
||||
fontname="Helvetica"
|
||||
node [fontname="Helvetica" fontsize=11 style=filled color="#333" fontcolor="#e5e5e5" shape=box]
|
||||
edge [fontname="Helvetica" fontsize=9 fontcolor="#a3a3a3" color="#666"]
|
||||
|
||||
label="Sidebar Injection — How Wrapping Works"
|
||||
labelloc=t
|
||||
fontsize=14
|
||||
fontcolor="#d4a574"
|
||||
|
||||
browser [label="Browser" fillcolor="#1a1a1a" shape=oval]
|
||||
|
||||
subgraph cluster_nginx {
|
||||
label="Nginx (reverse proxy)"
|
||||
style=dashed
|
||||
color="#d4a574"
|
||||
fontcolor="#d4a574"
|
||||
|
||||
proxy [label="proxy_pass\n+\nsub_filter\ninjects sidebar" fillcolor="#1a1a1a" shape=component]
|
||||
}
|
||||
|
||||
subgraph cluster_app {
|
||||
label="Managed App"
|
||||
style=dashed
|
||||
color="#333"
|
||||
fontcolor="#666"
|
||||
|
||||
frontend [label="Frontend\n(React/Next/Vue)" fillcolor="#1a1a1a"]
|
||||
backend [label="Backend API" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
subgraph cluster_spr {
|
||||
label="Soleprint"
|
||||
style=dashed
|
||||
color="#d4a574"
|
||||
fontcolor="#d4a574"
|
||||
|
||||
sidebar_css [label="sidebar.css" fillcolor="#1a1a1a"]
|
||||
sidebar_js [label="sidebar.js" fillcolor="#1a1a1a"]
|
||||
hub [label="Hub API\n/api/sidebar/config" fillcolor="#1a1a1a"]
|
||||
}
|
||||
|
||||
browser -> proxy [label="myroom.spr.local.ar"]
|
||||
proxy -> frontend [label="/ → app"]
|
||||
proxy -> hub [label="/spr/ → soleprint"]
|
||||
|
||||
// The injection
|
||||
proxy -> sidebar_css [label="injects into </head>" color="#d4a574" style=dashed]
|
||||
proxy -> sidebar_js [color="#d4a574" style=dashed]
|
||||
|
||||
sidebar_js -> hub [label="loads config" color="#d4a574"]
|
||||
}
|
||||
119
docs/graphs/wrapping.svg
Normal file
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.2 (0)
|
||||
-->
|
||||
<!-- Title: wrapping Pages: 1 -->
|
||||
<svg width="824pt" height="329pt"
|
||||
viewBox="0.00 0.00 824.00 329.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 325.41)">
|
||||
<title>wrapping</title>
|
||||
<polygon fill="#0a0a0a" stroke="none" points="-4,4 -4,-325.41 819.55,-325.41 819.55,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="407.78" y="-304.11" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Sidebar Injection — How Wrapping Works</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_nginx</title>
|
||||
<polygon fill="#0a0a0a" stroke="#d4a574" stroke-dasharray="5,2" points="193.3,-25.16 193.3,-128.16 360.05,-128.16 360.05,-25.16 193.3,-25.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="276.68" y="-110.86" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Nginx (reverse proxy)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_app</title>
|
||||
<polygon fill="#0a0a0a" stroke="#333333" stroke-dasharray="5,2" points="473.05,-157.16 473.05,-288.16 599.55,-288.16 599.55,-157.16 473.05,-157.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-270.86" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#666666">Managed App</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_spr</title>
|
||||
<polygon fill="#0a0a0a" stroke="#d4a574" stroke-dasharray="5,2" points="489.55,-18.16 489.55,-149.16 807.55,-149.16 807.55,-18.16 489.55,-18.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="648.55" y="-131.86" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d4a574">Soleprint</text>
|
||||
</g>
|
||||
<!-- browser -->
|
||||
<g id="node1" class="node">
|
||||
<title>browser</title>
|
||||
<ellipse fill="#1a1a1a" stroke="#333333" cx="38.03" cy="-64.16" rx="38.03" ry="18"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="38.03" y="-60.46" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Browser</text>
|
||||
</g>
|
||||
<!-- proxy -->
|
||||
<g id="node2" class="node">
|
||||
<title>proxy</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="324.3,-95.16 228.05,-95.16 228.05,-91.16 224.05,-91.16 224.05,-87.16 228.05,-87.16 228.05,-41.16 224.05,-41.16 224.05,-37.16 228.05,-37.16 228.05,-33.16 324.3,-33.16 324.3,-95.16"/>
|
||||
<polyline fill="none" stroke="#333333" points="228.05,-91.16 232.05,-91.16 232.05,-87.16 228.05,-87.16"/>
|
||||
<polyline fill="none" stroke="#333333" points="228.05,-41.16 232.05,-41.16 232.05,-37.16 228.05,-37.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="276.18" y="-80.71" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">proxy_pass</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="276.18" y="-67.21" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">+</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="276.18" y="-53.71" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">sub_filter</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="276.18" y="-40.21" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">injects sidebar</text>
|
||||
</g>
|
||||
<!-- browser->proxy -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>browser->proxy</title>
|
||||
<path fill="none" stroke="#666666" d="M76.45,-64.16C114.05,-64.16 172.57,-64.16 216.38,-64.16"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="216.24,-67.66 226.24,-64.16 216.24,-60.66 216.24,-67.66"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="138.68" y="-66.86" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">myroom.spr.local.ar</text>
|
||||
</g>
|
||||
<!-- frontend -->
|
||||
<g id="node3" class="node">
|
||||
<title>frontend</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="591.55,-201.16 481.05,-201.16 481.05,-165.16 591.55,-165.16 591.55,-201.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-186.21" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Frontend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-172.71" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">(React/Next/Vue)</text>
|
||||
</g>
|
||||
<!-- proxy->frontend -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>proxy->frontend</title>
|
||||
<path fill="none" stroke="#666666" d="M324.52,-85.99C370.03,-106.97 438.55,-138.56 485.02,-159.98"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="483.53,-163.15 494.08,-164.16 486.46,-156.79 483.53,-163.15"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="416.55" y="-150.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">/ → app</text>
|
||||
</g>
|
||||
<!-- sidebar_css -->
|
||||
<g id="node5" class="node">
|
||||
<title>sidebar_css</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="575.05,-116.16 497.55,-116.16 497.55,-80.16 575.05,-80.16 575.05,-116.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-94.46" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">sidebar.css</text>
|
||||
</g>
|
||||
<!-- proxy->sidebar_css -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>proxy->sidebar_css</title>
|
||||
<path fill="none" stroke="#d4a574" stroke-dasharray="5,2" d="M324.52,-70.4C370.27,-76.43 439.3,-85.52 485.78,-91.64"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="485.21,-95.09 495.58,-92.93 486.12,-88.15 485.21,-95.09"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="416.55" y="-90.82" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">injects into </head></text>
|
||||
</g>
|
||||
<!-- sidebar_js -->
|
||||
<g id="node6" class="node">
|
||||
<title>sidebar_js</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="570.55,-62.16 502.05,-62.16 502.05,-26.16 570.55,-26.16 570.55,-62.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-40.46" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">sidebar.js</text>
|
||||
</g>
|
||||
<!-- proxy->sidebar_js -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>proxy->sidebar_js</title>
|
||||
<path fill="none" stroke="#d4a574" stroke-dasharray="5,2" d="M324.52,-60.49C371.88,-56.82 444.19,-51.22 490.6,-47.63"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="490.6,-51.14 500.3,-46.87 490.06,-44.16 490.6,-51.14"/>
|
||||
</g>
|
||||
<!-- hub -->
|
||||
<g id="node7" class="node">
|
||||
<title>hub</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="799.55,-62.16 682.3,-62.16 682.3,-26.16 799.55,-26.16 799.55,-62.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="740.93" y="-47.21" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Hub API</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="740.93" y="-33.71" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">/api/sidebar/config</text>
|
||||
</g>
|
||||
<!-- proxy->hub -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>proxy->hub</title>
|
||||
<path fill="none" stroke="#666666" d="M324.6,-45.85C363.74,-31.76 421.09,-13.48 473.05,-5.91 528.69,2.18 543.83,1.54 599.55,-5.91 624.52,-9.25 651.33,-15.79 674.76,-22.54"/>
|
||||
<polygon fill="#666666" stroke="#666666" points="673.59,-25.84 684.17,-25.31 675.57,-19.12 673.59,-25.84"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-8.61" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">/spr/ → soleprint</text>
|
||||
</g>
|
||||
<!-- backend -->
|
||||
<g id="node4" class="node">
|
||||
<title>backend</title>
|
||||
<polygon fill="#1a1a1a" stroke="#333333" points="578.05,-255.16 494.55,-255.16 494.55,-219.16 578.05,-219.16 578.05,-255.16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="536.3" y="-233.46" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e5e5e5">Backend API</text>
|
||||
</g>
|
||||
<!-- sidebar_js->hub -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>sidebar_js->hub</title>
|
||||
<path fill="none" stroke="#d4a574" d="M570.76,-44.16C597.83,-44.16 636.85,-44.16 670.6,-44.16"/>
|
||||
<polygon fill="#d4a574" stroke="#d4a574" points="670.3,-47.66 680.3,-44.16 670.3,-40.66 670.3,-47.66"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="636.93" y="-46.86" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#a3a3a3">loads config</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.0 KiB |
273
docs/index.html
@@ -1,262 +1,19 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Soleprint - Documentation</title>
|
||||
<link rel="stylesheet" href="architecture/styles.css" />
|
||||
<style>
|
||||
.one-liner {
|
||||
font-size: 1.2rem;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.demo-link {
|
||||
display: inline-block;
|
||||
margin-top: 1rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--accent);
|
||||
color: var(--bg-primary);
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.demo-link:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.systems-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.system-card {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid var(--accent);
|
||||
}
|
||||
.system-card h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.system-card p {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.arch-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.arch-card {
|
||||
display: block;
|
||||
background: var(--bg-secondary);
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
transition: transform 0.15s;
|
||||
}
|
||||
.arch-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.arch-card h4 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.arch-card p {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
pre {
|
||||
background: var(--bg-primary);
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
<script src="lang-toggle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="lang-toggle"></div>
|
||||
<h1>Soleprint</h1>
|
||||
<p class="subtitle">Cada paso deja huella</p>
|
||||
<p class="one-liner">
|
||||
<span class="lang-en"
|
||||
>Pluggable stuff to tackle any challenge</span
|
||||
>
|
||||
<span class="lang-es"
|
||||
>Piezas enchufables para cualquier desafio</span
|
||||
>
|
||||
</p>
|
||||
<a href="https://sample.spr.mcrn.ar" class="demo-link">
|
||||
<span class="lang-en">Try the Demo</span>
|
||||
<span class="lang-es">Ver Demo</span>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">The Three Systems</span>
|
||||
<span class="lang-es">Los Tres Sistemas</span>
|
||||
</h2>
|
||||
<div class="systems-grid">
|
||||
<a
|
||||
href="artery/"
|
||||
class="system-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>Artery</h3>
|
||||
<p class="lang-en">
|
||||
API connectors and data flow. Veins for real APIs,
|
||||
shunts for mocks.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Conectores y flujo de datos. Veins para APIs reales,
|
||||
shunts para mocks.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="atlas/"
|
||||
class="system-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>Atlas</h3>
|
||||
<p class="lang-en">
|
||||
Actionable documentation. Templates that generate
|
||||
living docs.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Documentacion accionable. Templates que generan docs
|
||||
vivos.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="station/"
|
||||
class="system-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>Station</h3>
|
||||
<p class="lang-en">
|
||||
Tools and monitors. Everything to run, test, and
|
||||
observe.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Herramientas y monitores. Todo para correr, testear,
|
||||
y observar.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>Quick Start</h2>
|
||||
<pre>
|
||||
# Clone
|
||||
git clone https://git.mcrn.ar/soleprint
|
||||
cd soleprint
|
||||
|
||||
# Setup (once)
|
||||
python -m venv .venv && source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Option 1: Build standalone (soleprint only)
|
||||
python build.py --cfg standalone
|
||||
cd gen/standalone && ./ctrl/start.sh
|
||||
# Visit http://localhost:12000
|
||||
|
||||
# Option 2: Build managed room (soleprint + your app)
|
||||
python build.py --cfg myroom
|
||||
cd gen/myroom && ./ctrl/start.sh
|
||||
# Visit http://myroom.spr.local.ar
|
||||
|
||||
# Option 3: Use the installer (coming soon)</pre
|
||||
>
|
||||
|
||||
<p style="margin-top: 1rem">
|
||||
<span class="lang-en">Minimal config example:</span>
|
||||
<span class="lang-es">Ejemplo de config minima:</span>
|
||||
</p>
|
||||
<pre>
|
||||
// cfg/myroom/config.json
|
||||
{
|
||||
"room": "myroom",
|
||||
"artery": {
|
||||
"veins": ["google", "jira", "slack"],
|
||||
"shunts": ["mercadopago"]
|
||||
},
|
||||
"atlas": {
|
||||
"books": ["gherkin", "feature-flow"]
|
||||
},
|
||||
"station": {
|
||||
"tools": ["tester", "modelgen"],
|
||||
"monitors": ["databrowse"]
|
||||
}
|
||||
}</pre
|
||||
>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Architecture</span>
|
||||
<span class="lang-es">Arquitectura</span>
|
||||
</h2>
|
||||
<p class="lang-en">Deep dive into how soleprint works.</p>
|
||||
<p class="lang-es">Profundizando en como funciona soleprint.</p>
|
||||
<div class="findings-grid">
|
||||
<a
|
||||
href="architecture/"
|
||||
class="finding-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>
|
||||
<span class="lang-en">Architecture Diagrams →</span
|
||||
><span class="lang-es"
|
||||
>Diagramas de Arquitectura →</span
|
||||
>
|
||||
</h3>
|
||||
<p class="lang-en">
|
||||
System overview, artery hierarchy, build flow, room
|
||||
configuration.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Vista general, jerarquia de artery, flujo de build,
|
||||
configuracion de rooms.
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="architecture/sidebar-injection.html"
|
||||
class="finding-card"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
<h3>
|
||||
<span class="lang-en">Sidebar Injection →</span
|
||||
><span class="lang-es">Inyeccion de Sidebar →</span>
|
||||
</h3>
|
||||
<p class="lang-en">
|
||||
How the managed room sidebar works with nginx +
|
||||
JavaScript.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Como funciona el sidebar del managed room con nginx
|
||||
+ JavaScript.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Docs | soleprint</title>
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' fill='%23e5e5e5'%3E%3Cg transform='rotate(-15 18 38)'%3E%3Cellipse cx='18' cy='32' rx='7' ry='13'/%3E%3Cellipse cx='18' cy='48' rx='6' ry='7'/%3E%3C/g%3E%3Cg transform='rotate(15 46 28)'%3E%3Cellipse cx='46' cy='22' rx='7' ry='13'/%3E%3Cellipse cx='46' cy='38' rx='6' ry='7'/%3E%3C/g%3E%3C/svg%3E">
|
||||
<link rel="stylesheet" href="docs.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<nav class="sidebar" id="sidebar"></nav>
|
||||
<main class="content" id="content">
|
||||
<p class="loading">Loading...</p>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="https://soleprint.mcrn.ar">soleprint.mcrn.ar</a> ·
|
||||
<a href="https://sample.spr.mcrn.ar">Live Demo</a>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</div>
|
||||
<script src="docs.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
// Language toggle for soleprint docs
|
||||
// Include this script and add: <div id="lang-toggle"></div> in header
|
||||
|
||||
(function () {
|
||||
function setLang(lang) {
|
||||
localStorage.setItem("spr-docs-lang", lang);
|
||||
document.documentElement.lang = lang;
|
||||
document.querySelectorAll(".lang-toggle button").forEach((btn) => {
|
||||
btn.classList.toggle("active", btn.dataset.lang === lang);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const currentLang = localStorage.getItem("spr-docs-lang") || "en";
|
||||
|
||||
// Inject toggle HTML
|
||||
const container = document.getElementById("lang-toggle");
|
||||
if (container) {
|
||||
container.className = "lang-toggle";
|
||||
|
||||
const btnEn = document.createElement("button");
|
||||
btnEn.textContent = "EN";
|
||||
btnEn.dataset.lang = "en";
|
||||
btnEn.addEventListener("click", () => setLang("en"));
|
||||
|
||||
const btnEs = document.createElement("button");
|
||||
btnEs.textContent = "ES";
|
||||
btnEs.dataset.lang = "es";
|
||||
btnEs.addEventListener("click", () => setLang("es"));
|
||||
|
||||
container.appendChild(btnEn);
|
||||
container.appendChild(btnEs);
|
||||
}
|
||||
|
||||
setLang(currentLang);
|
||||
});
|
||||
|
||||
// Inject styles
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
.lang-toggle { position: absolute; top: 1.5rem; right: 2rem; display: flex; border: 1px solid #888; border-radius: 4px; overflow: hidden; }
|
||||
.lang-toggle button { background: #1a1a1a; border: none; color: #888; padding: 0.4rem 0.8rem; font-family: inherit; font-size: 0.75rem; cursor: pointer; }
|
||||
.lang-toggle button:first-child { border-right: 1px solid #888; }
|
||||
.lang-toggle button:hover { background: #0a0a0a; color: #fff; }
|
||||
.lang-toggle button.active { background: var(--accent, #b91c1c); color: #fff; }
|
||||
header { position: relative; }
|
||||
.lang-en, .lang-es { display: none; }
|
||||
html[lang="en"] .lang-en { display: block; }
|
||||
html[lang="es"] .lang-es { display: block; }
|
||||
html[lang="en"] span.lang-en { display: inline; }
|
||||
html[lang="es"] span.lang-es { display: inline; }
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
})();
|
||||
@@ -1,336 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Station - Soleprint</title>
|
||||
<link rel="stylesheet" href="../architecture/styles.css" />
|
||||
<style>
|
||||
.composition {
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #7c3aed;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.composition h3 {
|
||||
margin: 0 0 0.75rem 0;
|
||||
font-size: 1.1rem;
|
||||
color: #c4b5fd;
|
||||
}
|
||||
.composition > p {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 0.9rem;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.components {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.component {
|
||||
background: #0a0a0a;
|
||||
border: 1px solid #3f3f3f;
|
||||
padding: 0.75rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.component h4 {
|
||||
margin: 0 0 0.25rem 0;
|
||||
font-size: 0.95rem;
|
||||
color: #c4b5fd;
|
||||
}
|
||||
.component p {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.model-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
<script src="../lang-toggle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div id="lang-toggle"></div>
|
||||
<h1>Station</h1>
|
||||
<p class="subtitle">
|
||||
<span class="lang-en">Monitors, Environments & Tools</span
|
||||
><span class="lang-es">Monitores, Entornos y Herramientas</span>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Model</span
|
||||
><span class="lang-es">Modelo</span>
|
||||
</h2>
|
||||
<div class="model-grid">
|
||||
<div class="composition">
|
||||
<h3>Desk</h3>
|
||||
<p class="lang-en">
|
||||
Control center - collection of monitors
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Centro de control - coleccion de monitores
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>Monitor</h4>
|
||||
<p>Web UI</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Monitor</h4>
|
||||
<p>Web UI</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>...</h4>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="composition">
|
||||
<h3>Monitor</h3>
|
||||
<p class="lang-en">
|
||||
Web interface - always running, always watching
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Interfaz web - siempre corriendo, siempre observando
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>Web UI</h4>
|
||||
<p>Dashboard</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Room</h4>
|
||||
<p class="lang-en">Config/env</p>
|
||||
<p class="lang-es">Config/entorno</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Depot</h4>
|
||||
<p class="lang-en">Data source</p>
|
||||
<p class="lang-es">Fuente de datos</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="composition">
|
||||
<h3>Tool</h3>
|
||||
<p class="lang-en">
|
||||
CLI utility - run once, get results
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Utilidad CLI - ejecutar una vez, obtener resultados
|
||||
</p>
|
||||
<div class="components">
|
||||
<div class="component">
|
||||
<h4>CLI</h4>
|
||||
<p class="lang-en">Command interface</p>
|
||||
<p class="lang-es">Interfaz de comandos</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Room</h4>
|
||||
<p class="lang-en">Config/env</p>
|
||||
<p class="lang-es">Config/entorno</p>
|
||||
</div>
|
||||
<div class="component">
|
||||
<h4>Depot</h4>
|
||||
<p class="lang-en">Output storage</p>
|
||||
<p class="lang-es">Almacenamiento de salida</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Architecture</span
|
||||
><span class="lang-es">Arquitectura</span>
|
||||
</h2>
|
||||
<img
|
||||
src="../architecture/01-system-overview.svg"
|
||||
alt="System Overview"
|
||||
style="
|
||||
max-width: 100%;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Components</span
|
||||
><span class="lang-es">Componentes</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Desk</h3>
|
||||
<p class="lang-en">
|
||||
Collection of monitors. Your control center with all
|
||||
the views you need.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Coleccion de monitores. Tu centro de control con
|
||||
todas las vistas que necesitas.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Monitor</h3>
|
||||
<p class="lang-en">
|
||||
Web interfaces for observation. Data browsers,
|
||||
dashboards, log viewers. Always running.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Interfaces web para observacion. Navegadores de
|
||||
datos, dashboards, visores de logs. Siempre
|
||||
corriendo.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Tool</h3>
|
||||
<p class="lang-en">
|
||||
CLI utilities and scripts. Code generators, test
|
||||
runners, infra provisioners. Run once, get results.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Utilidades CLI y scripts. Generadores de codigo,
|
||||
test runners, provisioners de infra. Ejecutar una
|
||||
vez, obtener resultados.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Shared Components</span
|
||||
><span class="lang-es">Componentes Compartidos</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Room</h3>
|
||||
<p class="lang-en">
|
||||
Runtime environment configuration. Tools and
|
||||
monitors are configured per-room for isolation.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Configuracion del entorno. Tools y monitors se
|
||||
configuran por room para aislamiento.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Depot</h3>
|
||||
<p class="lang-en">
|
||||
Data storage. For tools: output files, results. For
|
||||
monitors: data to display.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Almacenamiento de datos. Para tools: archivos de
|
||||
salida, resultados. Para monitors: datos a mostrar.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Available Tools</span
|
||||
><span class="lang-es">Tools Disponibles</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>Tester</h3>
|
||||
<p class="lang-en">
|
||||
API and Playwright test runner. Discover tests, run
|
||||
them, collect artifacts.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Test runner de API y Playwright. Descubrir tests,
|
||||
ejecutarlos, recolectar artefactos.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>ModelGen</h3>
|
||||
<p class="lang-en">
|
||||
Generate model diagrams from code. Introspect
|
||||
soleprint structure, output SVG.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Generar diagramas de modelo desde codigo.
|
||||
Introspeccionar estructura de soleprint, generar
|
||||
SVG.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>Infra</h3>
|
||||
<p class="lang-en">
|
||||
Infrastructure provisioners. AWS, GCP, DigitalOcean
|
||||
deployment helpers.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Provisioners de infraestructura. Helpers de deploy
|
||||
para AWS, GCP, DigitalOcean.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>DataGen</h3>
|
||||
<p class="lang-en">
|
||||
Test data generation. Create realistic fake data for
|
||||
development.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Generacion de datos de test. Crear datos falsos
|
||||
realistas para desarrollo.
|
||||
</p>
|
||||
</article>
|
||||
<article class="finding-card">
|
||||
<h3>DataBrowse</h3>
|
||||
<p class="lang-en">
|
||||
Navigable data model graphs generated from existing
|
||||
models.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Grafos de modelo de datos navegables generados desde
|
||||
modelos existentes.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="findings-section">
|
||||
<h2>
|
||||
<span class="lang-en">Available Monitors</span
|
||||
><span class="lang-es">Monitors Disponibles</span>
|
||||
</h2>
|
||||
<div class="findings-grid">
|
||||
<article class="finding-card">
|
||||
<h3>DataBrowse</h3>
|
||||
<p class="lang-en">
|
||||
Navigable data model graphs generated from existing
|
||||
models.
|
||||
</p>
|
||||
<p class="lang-es">
|
||||
Grafos de modelo de datos navegables generados desde
|
||||
modelos existentes.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="../"
|
||||
><span class="lang-en">← Back to index</span
|
||||
><span class="lang-es">← Volver al indice</span></a
|
||||
>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,61 +0,0 @@
|
||||
digraph GoogleVein {
|
||||
rankdir=LR;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11, shape=box, style="rounded,filled"];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
labelloc="t";
|
||||
label="Google Vein - OAuth Flow";
|
||||
fontsize=16;
|
||||
|
||||
// Client
|
||||
subgraph cluster_client {
|
||||
label="Soleprint";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
app [label="Application", fillcolor="#C8E6C9"];
|
||||
vein [label="Google Vein\n(artery/veins/google)", fillcolor="#A5D6A7"];
|
||||
oauth [label="OAuth Handler\n(artery/oauth.py)", fillcolor="#81C784"];
|
||||
}
|
||||
|
||||
// OAuth Flow
|
||||
subgraph cluster_oauth {
|
||||
label="OAuth 2.0";
|
||||
style=filled;
|
||||
color="#FFF8E1";
|
||||
fillcolor="#FFF8E1";
|
||||
|
||||
auth_url [label="1. Authorization URL", fillcolor="#FFECB3"];
|
||||
consent [label="2. User Consent", fillcolor="#FFE082"];
|
||||
callback [label="3. Callback + Code", fillcolor="#FFD54F"];
|
||||
tokens [label="4. Access + Refresh\nTokens", fillcolor="#FFCA28"];
|
||||
}
|
||||
|
||||
// Google APIs
|
||||
subgraph cluster_google {
|
||||
label="Google APIs";
|
||||
style=filled;
|
||||
color="#E3F2FD";
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
sheets [label="Sheets API", fillcolor="#BBDEFB"];
|
||||
calendar [label="Calendar API", fillcolor="#BBDEFB"];
|
||||
drive [label="Drive API", fillcolor="#BBDEFB"];
|
||||
}
|
||||
|
||||
// Flow
|
||||
app -> vein [label="get_sheets()"];
|
||||
vein -> oauth [label="ensure_auth"];
|
||||
oauth -> auth_url;
|
||||
auth_url -> consent;
|
||||
consent -> callback;
|
||||
callback -> tokens;
|
||||
tokens -> oauth [label="store"];
|
||||
|
||||
oauth -> sheets [label="Bearer token"];
|
||||
oauth -> calendar [label="Bearer token"];
|
||||
oauth -> drive [label="Bearer token"];
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: GoogleVein Pages: 1 -->
|
||||
<svg width="1243pt" height="340pt"
|
||||
viewBox="0.00 0.00 1243.00 340.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 335.5)">
|
||||
<title>GoogleVein</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-335.5 1239.25,-335.5 1239.25,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="617.62" y="-312.3" font-family="Helvetica,sans-Serif" font-size="16.00">Google Vein - OAuth Flow</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_client</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="8,-74 8,-154 537,-154 537,-74 8,-74"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="272.5" y="-134.8" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_oauth</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="619.25,-216 619.25,-296 1227.25,-296 1227.25,-216 619.25,-216"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="923.25" y="-276.8" font-family="Helvetica,sans-Serif" font-size="16.00">OAuth 2.0</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_google</title>
|
||||
<polygon fill="#e3f2fd" stroke="#e3f2fd" points="636.38,-20 636.38,-208 748.38,-208 748.38,-20 636.38,-20"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="692.38" y="-188.8" font-family="Helvetica,sans-Serif" font-size="16.00">Google APIs</text>
|
||||
</g>
|
||||
<!-- app -->
|
||||
<g id="node1" class="node">
|
||||
<title>app</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M80.75,-118C80.75,-118 28,-118 28,-118 22,-118 16,-112 16,-106 16,-106 16,-94 16,-94 16,-88 22,-82 28,-82 28,-82 80.75,-82 80.75,-82 86.75,-82 92.75,-88 92.75,-94 92.75,-94 92.75,-106 92.75,-106 92.75,-112 86.75,-118 80.75,-118"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="54.38" y="-96.3" font-family="Helvetica,sans-Serif" font-size="11.00">Application</text>
|
||||
</g>
|
||||
<!-- vein -->
|
||||
<g id="node2" class="node">
|
||||
<title>vein</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M309.75,-118C309.75,-118 201.5,-118 201.5,-118 195.5,-118 189.5,-112 189.5,-106 189.5,-106 189.5,-94 189.5,-94 189.5,-88 195.5,-82 201.5,-82 201.5,-82 309.75,-82 309.75,-82 315.75,-82 321.75,-88 321.75,-94 321.75,-94 321.75,-106 321.75,-106 321.75,-112 315.75,-118 309.75,-118"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="255.62" y="-103.05" font-family="Helvetica,sans-Serif" font-size="11.00">Google Vein</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="255.62" y="-89.55" font-family="Helvetica,sans-Serif" font-size="11.00">(artery/veins/google)</text>
|
||||
</g>
|
||||
<!-- app->vein -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>app->vein</title>
|
||||
<path fill="none" stroke="black" d="M92.85,-100C116.74,-100 148.56,-100 177.65,-100"/>
|
||||
<polygon fill="black" stroke="black" points="177.56,-103.5 187.56,-100 177.56,-96.5 177.56,-103.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="141.12" y="-103.25" font-family="Helvetica,sans-Serif" font-size="10.00">get_sheets()</text>
|
||||
</g>
|
||||
<!-- oauth -->
|
||||
<g id="node3" class="node">
|
||||
<title>oauth</title>
|
||||
<path fill="#81c784" stroke="black" d="M517,-118C517,-118 429.75,-118 429.75,-118 423.75,-118 417.75,-112 417.75,-106 417.75,-106 417.75,-94 417.75,-94 417.75,-88 423.75,-82 429.75,-82 429.75,-82 517,-82 517,-82 523,-82 529,-88 529,-94 529,-94 529,-106 529,-106 529,-112 523,-118 517,-118"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="473.38" y="-103.05" font-family="Helvetica,sans-Serif" font-size="11.00">OAuth Handler</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="473.38" y="-89.55" font-family="Helvetica,sans-Serif" font-size="11.00">(artery/oauth.py)</text>
|
||||
</g>
|
||||
<!-- vein->oauth -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>vein->oauth</title>
|
||||
<path fill="none" stroke="black" d="M322.24,-100C348.92,-100 379.71,-100 406.43,-100"/>
|
||||
<polygon fill="black" stroke="black" points="406.09,-103.5 416.09,-100 406.09,-96.5 406.09,-103.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="369.75" y="-103.25" font-family="Helvetica,sans-Serif" font-size="10.00">ensure_auth</text>
|
||||
</g>
|
||||
<!-- auth_url -->
|
||||
<g id="node4" class="node">
|
||||
<title>auth_url</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M744.5,-260C744.5,-260 639.25,-260 639.25,-260 633.25,-260 627.25,-254 627.25,-248 627.25,-248 627.25,-236 627.25,-236 627.25,-230 633.25,-224 639.25,-224 639.25,-224 744.5,-224 744.5,-224 750.5,-224 756.5,-230 756.5,-236 756.5,-236 756.5,-248 756.5,-248 756.5,-254 750.5,-260 744.5,-260"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.88" y="-238.3" font-family="Helvetica,sans-Serif" font-size="11.00">1. Authorization URL</text>
|
||||
</g>
|
||||
<!-- oauth->auth_url -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>oauth->auth_url</title>
|
||||
<path fill="none" stroke="black" d="M494.27,-118.13C521.13,-141.94 571.17,-184 619.25,-212 623.25,-214.33 627.46,-216.57 631.76,-218.71"/>
|
||||
<polygon fill="black" stroke="black" points="629.98,-221.74 640.51,-222.85 632.97,-215.41 629.98,-221.74"/>
|
||||
</g>
|
||||
<!-- sheets -->
|
||||
<g id="node8" class="node">
|
||||
<title>sheets</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M717.12,-172C717.12,-172 666.62,-172 666.62,-172 660.62,-172 654.62,-166 654.62,-160 654.62,-160 654.62,-148 654.62,-148 654.62,-142 660.62,-136 666.62,-136 666.62,-136 717.12,-136 717.12,-136 723.12,-136 729.12,-142 729.12,-148 729.12,-148 729.12,-160 729.12,-160 729.12,-166 723.12,-172 717.12,-172"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.88" y="-150.3" font-family="Helvetica,sans-Serif" font-size="11.00">Sheets API</text>
|
||||
</g>
|
||||
<!-- oauth->sheets -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>oauth->sheets</title>
|
||||
<path fill="none" stroke="black" d="M529.29,-113.7C564.52,-122.48 609.79,-133.78 643.45,-142.17"/>
|
||||
<polygon fill="black" stroke="black" points="642.37,-145.51 652.92,-144.53 644.07,-138.72 642.37,-145.51"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="578.12" y="-136.67" font-family="Helvetica,sans-Serif" font-size="10.00">Bearer token</text>
|
||||
</g>
|
||||
<!-- calendar -->
|
||||
<g id="node9" class="node">
|
||||
<title>calendar</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M722.75,-118C722.75,-118 661,-118 661,-118 655,-118 649,-112 649,-106 649,-106 649,-94 649,-94 649,-88 655,-82 661,-82 661,-82 722.75,-82 722.75,-82 728.75,-82 734.75,-88 734.75,-94 734.75,-94 734.75,-106 734.75,-106 734.75,-112 728.75,-118 722.75,-118"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.88" y="-96.3" font-family="Helvetica,sans-Serif" font-size="11.00">Calendar API</text>
|
||||
</g>
|
||||
<!-- oauth->calendar -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>oauth->calendar</title>
|
||||
<path fill="none" stroke="black" d="M529.29,-100C562.46,-100 604.54,-100 637.44,-100"/>
|
||||
<polygon fill="black" stroke="black" points="637.15,-103.5 647.15,-100 637.15,-96.5 637.15,-103.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="578.12" y="-103.25" font-family="Helvetica,sans-Serif" font-size="10.00">Bearer token</text>
|
||||
</g>
|
||||
<!-- drive -->
|
||||
<g id="node10" class="node">
|
||||
<title>drive</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M713,-64C713,-64 670.75,-64 670.75,-64 664.75,-64 658.75,-58 658.75,-52 658.75,-52 658.75,-40 658.75,-40 658.75,-34 664.75,-28 670.75,-28 670.75,-28 713,-28 713,-28 719,-28 725,-34 725,-40 725,-40 725,-52 725,-52 725,-58 719,-64 713,-64"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="691.88" y="-42.3" font-family="Helvetica,sans-Serif" font-size="11.00">Drive API</text>
|
||||
</g>
|
||||
<!-- oauth->drive -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>oauth->drive</title>
|
||||
<path fill="none" stroke="black" d="M529.29,-86.3C565.98,-77.15 613.57,-65.28 647.58,-56.8"/>
|
||||
<polygon fill="black" stroke="black" points="648.24,-60.24 657.09,-54.43 646.54,-53.45 648.24,-60.24"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="578.12" y="-84.24" font-family="Helvetica,sans-Serif" font-size="10.00">Bearer token</text>
|
||||
</g>
|
||||
<!-- consent -->
|
||||
<g id="node5" class="node">
|
||||
<title>consent</title>
|
||||
<path fill="#ffe082" stroke="black" d="M886,-260C886,-260 805.5,-260 805.5,-260 799.5,-260 793.5,-254 793.5,-248 793.5,-248 793.5,-236 793.5,-236 793.5,-230 799.5,-224 805.5,-224 805.5,-224 886,-224 886,-224 892,-224 898,-230 898,-236 898,-236 898,-248 898,-248 898,-254 892,-260 886,-260"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="845.75" y="-238.3" font-family="Helvetica,sans-Serif" font-size="11.00">2. User Consent</text>
|
||||
</g>
|
||||
<!-- auth_url->consent -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>auth_url->consent</title>
|
||||
<path fill="none" stroke="black" d="M756.84,-242C765.11,-242 773.57,-242 781.82,-242"/>
|
||||
<polygon fill="black" stroke="black" points="781.78,-245.5 791.78,-242 781.78,-238.5 781.78,-245.5"/>
|
||||
</g>
|
||||
<!-- callback -->
|
||||
<g id="node6" class="node">
|
||||
<title>callback</title>
|
||||
<path fill="#ffd54f" stroke="black" d="M1043.25,-260C1043.25,-260 947,-260 947,-260 941,-260 935,-254 935,-248 935,-248 935,-236 935,-236 935,-230 941,-224 947,-224 947,-224 1043.25,-224 1043.25,-224 1049.25,-224 1055.25,-230 1055.25,-236 1055.25,-236 1055.25,-248 1055.25,-248 1055.25,-254 1049.25,-260 1043.25,-260"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="995.12" y="-238.3" font-family="Helvetica,sans-Serif" font-size="11.00">3. Callback + Code</text>
|
||||
</g>
|
||||
<!-- consent->callback -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>consent->callback</title>
|
||||
<path fill="none" stroke="black" d="M898.29,-242C906.34,-242 914.78,-242 923.16,-242"/>
|
||||
<polygon fill="black" stroke="black" points="923.02,-245.5 933.02,-242 923.02,-238.5 923.02,-245.5"/>
|
||||
</g>
|
||||
<!-- tokens -->
|
||||
<g id="node7" class="node">
|
||||
<title>tokens</title>
|
||||
<path fill="#ffca28" stroke="black" d="M1207.25,-260C1207.25,-260 1104.25,-260 1104.25,-260 1098.25,-260 1092.25,-254 1092.25,-248 1092.25,-248 1092.25,-236 1092.25,-236 1092.25,-230 1098.25,-224 1104.25,-224 1104.25,-224 1207.25,-224 1207.25,-224 1213.25,-224 1219.25,-230 1219.25,-236 1219.25,-236 1219.25,-248 1219.25,-248 1219.25,-254 1213.25,-260 1207.25,-260"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1155.75" y="-245.05" font-family="Helvetica,sans-Serif" font-size="11.00">4. Access + Refresh</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="1155.75" y="-231.55" font-family="Helvetica,sans-Serif" font-size="11.00">Tokens</text>
|
||||
</g>
|
||||
<!-- callback->tokens -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>callback->tokens</title>
|
||||
<path fill="none" stroke="black" d="M1055.64,-242C1063.8,-242 1072.26,-242 1080.64,-242"/>
|
||||
<polygon fill="black" stroke="black" points="1080.47,-245.5 1090.47,-242 1080.47,-238.5 1080.47,-245.5"/>
|
||||
</g>
|
||||
<!-- tokens->oauth -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>tokens->oauth</title>
|
||||
<path fill="none" stroke="black" d="M1151.88,-223.81C1141.88,-167.53 1103.13,0 996.12,0 690.88,0 690.88,0 690.88,0 619.58,0 546.24,-45.24 505.87,-74.87"/>
|
||||
<polygon fill="black" stroke="black" points="503.92,-71.95 498.02,-80.75 508.12,-77.55 503.92,-71.95"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="845.75" y="-3.25" font-family="Helvetica,sans-Serif" font-size="10.00">store</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,115 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Graph Viewer - Veins</title>
|
||||
<link rel="stylesheet" href="../architecture/styles.css" />
|
||||
</head>
|
||||
<body class="graph-viewer">
|
||||
<header class="graph-header">
|
||||
<a href="index.html" class="back-link">← Back</a>
|
||||
<div class="nav-controls">
|
||||
<button onclick="navigate(-1)" id="btn-prev" title="Previous">◀</button>
|
||||
<span id="nav-position">1 / 4</span>
|
||||
<button onclick="navigate(1)" id="btn-next" title="Next">▶</button>
|
||||
</div>
|
||||
<h1 id="graph-title">Loading...</h1>
|
||||
<div class="graph-controls">
|
||||
<button onclick="setMode('fit')">Fit</button>
|
||||
<button onclick="setMode('fit-width')">Width</button>
|
||||
<button onclick="setMode('fit-height')">Height</button>
|
||||
<button onclick="setMode('actual-size')">100%</button>
|
||||
<button onclick="downloadSvg()">↓ SVG</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="graph-container" id="graph-container">
|
||||
<img id="graph-img" src="" alt="Graph" />
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const graphOrder = [
|
||||
"jira",
|
||||
"slack",
|
||||
"google",
|
||||
"mercadopago-shunt",
|
||||
];
|
||||
|
||||
const graphs = {
|
||||
"jira": {
|
||||
title: "Jira Vein",
|
||||
file: "jira.svg",
|
||||
},
|
||||
"slack": {
|
||||
title: "Slack Vein",
|
||||
file: "slack.svg",
|
||||
},
|
||||
"google": {
|
||||
title: "Google Vein (OAuth)",
|
||||
file: "google.svg",
|
||||
},
|
||||
"mercadopago-shunt": {
|
||||
title: "MercadoPago Shunt",
|
||||
file: "mercadopago-shunt.svg",
|
||||
},
|
||||
};
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
let graphKey = params.get("g") || "jira";
|
||||
let currentIndex = graphOrder.indexOf(graphKey);
|
||||
if (currentIndex === -1) currentIndex = 0;
|
||||
|
||||
function loadGraph(key) {
|
||||
const graph = graphs[key];
|
||||
document.getElementById("graph-title").textContent = graph.title;
|
||||
document.getElementById("graph-img").src = graph.file;
|
||||
document.title = graph.title + " - Soleprint";
|
||||
history.replaceState(null, "", "?g=" + key);
|
||||
graphKey = key;
|
||||
updateNavHints();
|
||||
}
|
||||
|
||||
function updateNavHints() {
|
||||
const idx = graphOrder.indexOf(graphKey);
|
||||
const prevBtn = document.getElementById("btn-prev");
|
||||
const nextBtn = document.getElementById("btn-next");
|
||||
prevBtn.disabled = idx === 0;
|
||||
nextBtn.disabled = idx === graphOrder.length - 1;
|
||||
document.getElementById("nav-position").textContent =
|
||||
idx + 1 + " / " + graphOrder.length;
|
||||
}
|
||||
|
||||
function navigate(direction) {
|
||||
const idx = graphOrder.indexOf(graphKey);
|
||||
const newIdx = idx + direction;
|
||||
if (newIdx >= 0 && newIdx < graphOrder.length) {
|
||||
currentIndex = newIdx;
|
||||
loadGraph(graphOrder[newIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
function setMode(mode) {
|
||||
const container = document.getElementById("graph-container");
|
||||
container.className = "graph-container " + mode;
|
||||
}
|
||||
|
||||
function downloadSvg() {
|
||||
const graph = graphs[graphKey];
|
||||
const link = document.createElement("a");
|
||||
link.href = graph.file;
|
||||
link.download = graph.file;
|
||||
link.click();
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "ArrowLeft") navigate(-1);
|
||||
else if (e.key === "ArrowRight") navigate(1);
|
||||
else if (e.key === "Escape") window.location.href = "index.html";
|
||||
});
|
||||
|
||||
loadGraph(graphOrder[currentIndex]);
|
||||
setMode("fit");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,172 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Veins & Shunts - Soleprint</title>
|
||||
<link rel="stylesheet" href="../architecture/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Veins & Shunts</h1>
|
||||
<p class="subtitle">API Connectors & Mock Services</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="findings-section">
|
||||
<p style="margin-bottom: 1rem;"><a href="../index.html" style="color: var(--accent);">← Back to Docs</a></p>
|
||||
</section>
|
||||
|
||||
<!-- Veins -->
|
||||
<section class="graph-section">
|
||||
<h2 style="color: var(--accent); margin-bottom: 1rem;">Veins (Stateless API Connectors)</h2>
|
||||
<p style="color: var(--text-secondary); margin-bottom: 1.5rem;">
|
||||
Veins are stateless connectors to external APIs. They handle authentication and provide a clean interface for the rest of the application.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="graph-section" id="jira">
|
||||
<div class="graph-header-row">
|
||||
<h2>Jira</h2>
|
||||
<a href="graph.html?g=jira" class="view-btn">View Full</a>
|
||||
</div>
|
||||
<a href="graph.html?g=jira" class="graph-preview">
|
||||
<img src="jira.svg" alt="Jira Vein" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>Connect to Jira Cloud for issue tracking.</p>
|
||||
<h4>Capabilities</h4>
|
||||
<ul>
|
||||
<li>Get/create/update issues</li>
|
||||
<li>JQL search</li>
|
||||
<li>Transition issues between statuses</li>
|
||||
<li>List projects</li>
|
||||
</ul>
|
||||
<h4>Auth</h4>
|
||||
<p>API Token (Basic Auth with email + token)</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="graph-section" id="slack">
|
||||
<div class="graph-header-row">
|
||||
<h2>Slack</h2>
|
||||
<a href="graph.html?g=slack" class="view-btn">View Full</a>
|
||||
</div>
|
||||
<a href="graph.html?g=slack" class="graph-preview">
|
||||
<img src="slack.svg" alt="Slack Vein" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>Send messages and interact with Slack workspaces.</p>
|
||||
<h4>Capabilities</h4>
|
||||
<ul>
|
||||
<li>Post messages to channels</li>
|
||||
<li>List channels and users</li>
|
||||
<li>Upload files</li>
|
||||
<li>Webhook integration</li>
|
||||
</ul>
|
||||
<h4>Auth</h4>
|
||||
<p>Bot Token (Bearer)</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="graph-section" id="google">
|
||||
<div class="graph-header-row">
|
||||
<h2>Google</h2>
|
||||
<a href="graph.html?g=google" class="view-btn">View Full</a>
|
||||
</div>
|
||||
<a href="graph.html?g=google" class="graph-preview">
|
||||
<img src="google.svg" alt="Google Vein" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>Access Google Sheets, Calendar, Drive via OAuth 2.0.</p>
|
||||
<h4>Capabilities</h4>
|
||||
<ul>
|
||||
<li>Read/write Sheets</li>
|
||||
<li>Calendar events</li>
|
||||
<li>Drive file access</li>
|
||||
</ul>
|
||||
<h4>Auth</h4>
|
||||
<p>OAuth 2.0 with refresh tokens</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Shunts -->
|
||||
<section class="graph-section" style="margin-top: 3rem;">
|
||||
<h2 style="color: var(--accent); margin-bottom: 1rem;">Shunts (Mock Connectors)</h2>
|
||||
<p style="color: var(--text-secondary); margin-bottom: 1.5rem;">
|
||||
Shunts are fake connectors for testing. They mimic real APIs but let you control the responses.
|
||||
Perfect for testing payment flows, webhook handling, and integration scenarios without needing real credentials.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="graph-section" id="mercadopago">
|
||||
<div class="graph-header-row">
|
||||
<h2>MercadoPago Shunt</h2>
|
||||
<a href="graph.html?g=mercadopago-shunt" class="view-btn">View Full</a>
|
||||
</div>
|
||||
<a href="graph.html?g=mercadopago-shunt" class="graph-preview">
|
||||
<img src="mercadopago-shunt.svg" alt="MercadoPago Shunt" />
|
||||
</a>
|
||||
<div class="graph-details">
|
||||
<p>Mock MercadoPago payment API for testing payment flows.</p>
|
||||
<h4>Features</h4>
|
||||
<ul>
|
||||
<li>Fake payment creation</li>
|
||||
<li>Configurable responses (approved/pending/rejected)</li>
|
||||
<li>Webhook callbacks</li>
|
||||
<li>Config UI to set next response</li>
|
||||
</ul>
|
||||
<h4>Use Case</h4>
|
||||
<p>Test checkout flows without real payments. Set the shunt to return "approved" or "rejected" and verify your app handles each case.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Pattern -->
|
||||
<section class="tech-section">
|
||||
<h2>Vein Pattern</h2>
|
||||
<div class="tech-grid">
|
||||
<div class="tech-column">
|
||||
<h3>Structure</h3>
|
||||
<ul>
|
||||
<li>artery/veins/{name}/</li>
|
||||
<li>__init__.py (exports)</li>
|
||||
<li>client.py (API client)</li>
|
||||
<li>models.py (types)</li>
|
||||
<li>templates/ (test UI)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>Base Class</h3>
|
||||
<ul>
|
||||
<li>Extends artery/veins/base.py</li>
|
||||
<li>Common auth handling</li>
|
||||
<li>Request/response logging</li>
|
||||
<li>Error handling</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>OAuth</h3>
|
||||
<ul>
|
||||
<li>artery/oauth.py</li>
|
||||
<li>Token storage</li>
|
||||
<li>Refresh flow</li>
|
||||
<li>Callback handling</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tech-column">
|
||||
<h3>Config</h3>
|
||||
<ul>
|
||||
<li>cfg/{room}/data/veins.json</li>
|
||||
<li>Per-room credentials</li>
|
||||
<li>Enable/disable veins</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>Soleprint - Veins & Shunts Documentation</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,53 +0,0 @@
|
||||
digraph JiraVein {
|
||||
rankdir=LR;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11, shape=box, style="rounded,filled"];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
labelloc="t";
|
||||
label="Jira Vein - API Flow";
|
||||
fontsize=16;
|
||||
|
||||
// Client
|
||||
subgraph cluster_client {
|
||||
label="Soleprint";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
app [label="Application", fillcolor="#C8E6C9"];
|
||||
vein [label="Jira Vein\n(artery/veins/jira)", fillcolor="#A5D6A7"];
|
||||
}
|
||||
|
||||
// Auth
|
||||
subgraph cluster_auth {
|
||||
label="Authentication";
|
||||
style=filled;
|
||||
color="#FFF8E1";
|
||||
fillcolor="#FFF8E1";
|
||||
|
||||
token [label="API Token\n(Basic Auth)", fillcolor="#FFECB3"];
|
||||
}
|
||||
|
||||
// Jira API
|
||||
subgraph cluster_jira {
|
||||
label="Jira Cloud API";
|
||||
style=filled;
|
||||
color="#E3F2FD";
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
issues [label="/rest/api/3/issue", fillcolor="#BBDEFB"];
|
||||
search [label="/rest/api/3/search", fillcolor="#BBDEFB"];
|
||||
projects [label="/rest/api/3/project", fillcolor="#BBDEFB"];
|
||||
transitions [label="/rest/api/3/issue/{id}/transitions", fillcolor="#BBDEFB"];
|
||||
}
|
||||
|
||||
// Flow
|
||||
app -> vein [label="get_issue()"];
|
||||
vein -> token [label="auth"];
|
||||
token -> issues [label="GET/POST"];
|
||||
token -> search [label="JQL"];
|
||||
token -> projects [label="list"];
|
||||
token -> transitions [label="update status"];
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: JiraVein Pages: 1 -->
|
||||
<svg width="792pt" height="294pt"
|
||||
viewBox="0.00 0.00 792.00 294.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 289.5)">
|
||||
<title>JiraVein</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-289.5 788.25,-289.5 788.25,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="392.12" y="-266.3" font-family="Helvetica,sans-Serif" font-size="16.00">Jira Vein - API Flow</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_client</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="8,-88 8,-168 303.5,-168 303.5,-88 8,-88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="155.75" y="-148.8" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_auth</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="345.25,-88 345.25,-168 479.75,-168 479.75,-88 345.25,-88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="412.5" y="-148.8" font-family="Helvetica,sans-Serif" font-size="16.00">Authentication</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_jira</title>
|
||||
<polygon fill="#e3f2fd" stroke="#e3f2fd" points="566.5,-8 566.5,-250 776.25,-250 776.25,-8 566.5,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="671.38" y="-230.8" font-family="Helvetica,sans-Serif" font-size="16.00">Jira Cloud API</text>
|
||||
</g>
|
||||
<!-- app -->
|
||||
<g id="node1" class="node">
|
||||
<title>app</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M80.75,-132C80.75,-132 28,-132 28,-132 22,-132 16,-126 16,-120 16,-120 16,-108 16,-108 16,-102 22,-96 28,-96 28,-96 80.75,-96 80.75,-96 86.75,-96 92.75,-102 92.75,-108 92.75,-108 92.75,-120 92.75,-120 92.75,-126 86.75,-132 80.75,-132"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="54.38" y="-110.3" font-family="Helvetica,sans-Serif" font-size="11.00">Application</text>
|
||||
</g>
|
||||
<!-- vein -->
|
||||
<g id="node2" class="node">
|
||||
<title>vein</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M283.5,-132C283.5,-132 194.75,-132 194.75,-132 188.75,-132 182.75,-126 182.75,-120 182.75,-120 182.75,-108 182.75,-108 182.75,-102 188.75,-96 194.75,-96 194.75,-96 283.5,-96 283.5,-96 289.5,-96 295.5,-102 295.5,-108 295.5,-108 295.5,-120 295.5,-120 295.5,-126 289.5,-132 283.5,-132"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239.12" y="-117.05" font-family="Helvetica,sans-Serif" font-size="11.00">Jira Vein</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="239.12" y="-103.55" font-family="Helvetica,sans-Serif" font-size="11.00">(artery/veins/jira)</text>
|
||||
</g>
|
||||
<!-- app->vein -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>app->vein</title>
|
||||
<path fill="none" stroke="black" d="M93.24,-114C115.64,-114 144.67,-114 170.86,-114"/>
|
||||
<polygon fill="black" stroke="black" points="170.75,-117.5 180.75,-114 170.75,-110.5 170.75,-117.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="137.75" y="-117.25" font-family="Helvetica,sans-Serif" font-size="10.00">get_issue()</text>
|
||||
</g>
|
||||
<!-- token -->
|
||||
<g id="node3" class="node">
|
||||
<title>token</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M441.75,-132C441.75,-132 382.25,-132 382.25,-132 376.25,-132 370.25,-126 370.25,-120 370.25,-120 370.25,-108 370.25,-108 370.25,-102 376.25,-96 382.25,-96 382.25,-96 441.75,-96 441.75,-96 447.75,-96 453.75,-102 453.75,-108 453.75,-108 453.75,-120 453.75,-120 453.75,-126 447.75,-132 441.75,-132"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="412" y="-117.05" font-family="Helvetica,sans-Serif" font-size="11.00">API Token</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="412" y="-103.55" font-family="Helvetica,sans-Serif" font-size="11.00">(Basic Auth)</text>
|
||||
</g>
|
||||
<!-- vein->token -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>vein->token</title>
|
||||
<path fill="none" stroke="black" d="M295.6,-114C315.81,-114 338.57,-114 358.5,-114"/>
|
||||
<polygon fill="black" stroke="black" points="358.36,-117.5 368.36,-114 358.36,-110.5 358.36,-117.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="324.38" y="-117.25" font-family="Helvetica,sans-Serif" font-size="10.00">auth</text>
|
||||
</g>
|
||||
<!-- issues -->
|
||||
<g id="node4" class="node">
|
||||
<title>issues</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M711.62,-214C711.62,-214 631.12,-214 631.12,-214 625.12,-214 619.12,-208 619.12,-202 619.12,-202 619.12,-190 619.12,-190 619.12,-184 625.12,-178 631.12,-178 631.12,-178 711.62,-178 711.62,-178 717.62,-178 723.62,-184 723.62,-190 723.62,-190 723.62,-202 723.62,-202 723.62,-208 717.62,-214 711.62,-214"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="671.38" y="-192.3" font-family="Helvetica,sans-Serif" font-size="11.00">/rest/api/3/issue</text>
|
||||
</g>
|
||||
<!-- token->issues -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>token->issues</title>
|
||||
<path fill="none" stroke="black" d="M454.12,-132.07C465.56,-136.84 478.06,-141.82 489.75,-146 528.32,-159.78 572.63,-172.1 607.71,-181.06"/>
|
||||
<polygon fill="black" stroke="black" points="606.74,-184.42 617.29,-183.48 608.45,-177.63 606.74,-184.42"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="523.12" y="-169.6" font-family="Helvetica,sans-Serif" font-size="10.00">GET/POST</text>
|
||||
</g>
|
||||
<!-- search -->
|
||||
<g id="node5" class="node">
|
||||
<title>search</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M715.75,-160C715.75,-160 627,-160 627,-160 621,-160 615,-154 615,-148 615,-148 615,-136 615,-136 615,-130 621,-124 627,-124 627,-124 715.75,-124 715.75,-124 721.75,-124 727.75,-130 727.75,-136 727.75,-136 727.75,-148 727.75,-148 727.75,-154 721.75,-160 715.75,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="671.38" y="-138.3" font-family="Helvetica,sans-Serif" font-size="11.00">/rest/api/3/search</text>
|
||||
</g>
|
||||
<!-- token->search -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>token->search</title>
|
||||
<path fill="none" stroke="black" d="M454.07,-118.47C494.19,-122.83 555.94,-129.55 603.22,-134.69"/>
|
||||
<polygon fill="black" stroke="black" points="602.77,-138.17 613.09,-135.77 603.53,-131.21 602.77,-138.17"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="523.12" y="-132.09" font-family="Helvetica,sans-Serif" font-size="10.00">JQL</text>
|
||||
</g>
|
||||
<!-- projects -->
|
||||
<g id="node6" class="node">
|
||||
<title>projects</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M716.5,-106C716.5,-106 626.25,-106 626.25,-106 620.25,-106 614.25,-100 614.25,-94 614.25,-94 614.25,-82 614.25,-82 614.25,-76 620.25,-70 626.25,-70 626.25,-70 716.5,-70 716.5,-70 722.5,-70 728.5,-76 728.5,-82 728.5,-82 728.5,-94 728.5,-94 728.5,-100 722.5,-106 716.5,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="671.38" y="-84.3" font-family="Helvetica,sans-Serif" font-size="11.00">/rest/api/3/project</text>
|
||||
</g>
|
||||
<!-- token->projects -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>token->projects</title>
|
||||
<path fill="none" stroke="black" d="M453.95,-107.16C465.5,-105.39 478.1,-103.6 489.75,-102.25 527.09,-97.92 568.92,-94.53 602.92,-92.14"/>
|
||||
<polygon fill="black" stroke="black" points="602.89,-95.66 612.62,-91.48 602.41,-88.67 602.89,-95.66"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="523.12" y="-105.5" font-family="Helvetica,sans-Serif" font-size="10.00">list</text>
|
||||
</g>
|
||||
<!-- transitions -->
|
||||
<g id="node7" class="node">
|
||||
<title>transitions</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M756.25,-52C756.25,-52 586.5,-52 586.5,-52 580.5,-52 574.5,-46 574.5,-40 574.5,-40 574.5,-28 574.5,-28 574.5,-22 580.5,-16 586.5,-16 586.5,-16 756.25,-16 756.25,-16 762.25,-16 768.25,-22 768.25,-28 768.25,-28 768.25,-40 768.25,-40 768.25,-46 762.25,-52 756.25,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="671.38" y="-30.3" font-family="Helvetica,sans-Serif" font-size="11.00">/rest/api/3/issue/{id}/transitions</text>
|
||||
</g>
|
||||
<!-- token->transitions -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>token->transitions</title>
|
||||
<path fill="none" stroke="black" d="M449.93,-95.66C462.38,-89.91 476.49,-83.87 489.75,-79.25 516.18,-70.04 545.39,-61.89 572.48,-55.12"/>
|
||||
<polygon fill="black" stroke="black" points="573.19,-58.55 582.07,-52.77 571.52,-51.75 573.19,-58.55"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="523.12" y="-82.5" font-family="Helvetica,sans-Serif" font-size="10.00">update status</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.3 KiB |
@@ -1,64 +0,0 @@
|
||||
digraph MercadoPagoShunt {
|
||||
rankdir=LR;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11, shape=box, style="rounded,filled"];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
labelloc="t";
|
||||
label="MercadoPago Shunt - Mock Payment Flow";
|
||||
fontsize=16;
|
||||
|
||||
// Client App
|
||||
subgraph cluster_client {
|
||||
label="Managed Room (e.g., AMAR)";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
backend [label="Backend\n(Django/FastAPI)", fillcolor="#C8E6C9"];
|
||||
}
|
||||
|
||||
// Shunt
|
||||
subgraph cluster_shunt {
|
||||
label="Shunt (artery/shunts/mercadopago)";
|
||||
style=filled;
|
||||
color="#FFF3E0";
|
||||
fillcolor="#FFF3E0";
|
||||
|
||||
mock_api [label="Mock API\n/payments\n/preferences", fillcolor="#FFCC80"];
|
||||
config_ui [label="Config UI\n(set responses)", fillcolor="#FFB74D"];
|
||||
state [label="State\n(pending payments)", fillcolor="#FFA726"];
|
||||
}
|
||||
|
||||
// Fake responses
|
||||
subgraph cluster_responses {
|
||||
label="Configurable Responses";
|
||||
style=dashed;
|
||||
color=gray;
|
||||
|
||||
approved [label="approved", fillcolor="#C8E6C9"];
|
||||
pending [label="pending", fillcolor="#FFF9C4"];
|
||||
rejected [label="rejected", fillcolor="#FFCDD2"];
|
||||
}
|
||||
|
||||
// Real (bypassed)
|
||||
subgraph cluster_real {
|
||||
label="Real MercadoPago (bypassed)";
|
||||
style=dashed;
|
||||
color="#BDBDBD";
|
||||
|
||||
real_api [label="api.mercadopago.com", fillcolor="#E0E0E0", fontcolor="#9E9E9E"];
|
||||
}
|
||||
|
||||
// Flow
|
||||
backend -> mock_api [label="POST /payments"];
|
||||
mock_api -> state [label="store"];
|
||||
config_ui -> state [label="configure"];
|
||||
|
||||
state -> approved [style=dashed];
|
||||
state -> pending [style=dashed];
|
||||
state -> rejected [style=dashed];
|
||||
|
||||
mock_api -> backend [label="webhook callback", style=dashed];
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: MercadoPagoShunt Pages: 1 -->
|
||||
<svg width="931pt" height="240pt"
|
||||
viewBox="0.00 0.00 931.00 240.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 235.5)">
|
||||
<title>MercadoPagoShunt</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-235.5 926.75,-235.5 926.75,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="461.38" y="-212.3" font-family="Helvetica,sans-Serif" font-size="16.00">MercadoPago Shunt - Mock Payment Flow</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_client</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="5.25,-16 5.25,-96 252.25,-96 252.25,-16 5.25,-16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="128.75" y="-76.8" font-family="Helvetica,sans-Serif" font-size="16.00">Managed Room (e.g., AMAR)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_shunt</title>
|
||||
<polygon fill="#fff3e0" stroke="#fff3e0" points="365.25,-13 365.25,-159 691.5,-159 691.5,-13 365.25,-13"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="528.38" y="-139.8" font-family="Helvetica,sans-Serif" font-size="16.00">Shunt (artery/shunts/mercadopago)</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_responses</title>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="712.5,-8 712.5,-196 922.75,-196 922.75,-8 712.5,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="817.62" y="-176.8" font-family="Helvetica,sans-Serif" font-size="16.00">Configurable Responses</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_real</title>
|
||||
<polygon fill="none" stroke="#bdbdbd" stroke-dasharray="5,2" points="0,-105 0,-185 257.5,-185 257.5,-105 0,-105"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="128.75" y="-165.8" font-family="Helvetica,sans-Serif" font-size="16.00">Real MercadoPago (bypassed)</text>
|
||||
</g>
|
||||
<!-- backend -->
|
||||
<g id="node1" class="node">
|
||||
<title>backend</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M169.62,-60C169.62,-60 86.88,-60 86.88,-60 80.88,-60 74.88,-54 74.88,-48 74.88,-48 74.88,-36 74.88,-36 74.88,-30 80.88,-24 86.88,-24 86.88,-24 169.62,-24 169.62,-24 175.62,-24 181.62,-30 181.62,-36 181.62,-36 181.62,-48 181.62,-48 181.62,-54 175.62,-60 169.62,-60"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="128.25" y="-45.05" font-family="Helvetica,sans-Serif" font-size="11.00">Backend</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="128.25" y="-31.55" font-family="Helvetica,sans-Serif" font-size="11.00">(Django/FastAPI)</text>
|
||||
</g>
|
||||
<!-- mock_api -->
|
||||
<g id="node2" class="node">
|
||||
<title>mock_api</title>
|
||||
<path fill="#ffcc80" stroke="black" d="M454.88,-69.25C454.88,-69.25 393.88,-69.25 393.88,-69.25 387.88,-69.25 381.88,-63.25 381.88,-57.25 381.88,-57.25 381.88,-32.75 381.88,-32.75 381.88,-26.75 387.88,-20.75 393.88,-20.75 393.88,-20.75 454.88,-20.75 454.88,-20.75 460.88,-20.75 466.88,-26.75 466.88,-32.75 466.88,-32.75 466.88,-57.25 466.88,-57.25 466.88,-63.25 460.88,-69.25 454.88,-69.25"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="424.38" y="-54.8" font-family="Helvetica,sans-Serif" font-size="11.00">Mock API</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="424.38" y="-41.3" font-family="Helvetica,sans-Serif" font-size="11.00">/payments</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="424.38" y="-27.8" font-family="Helvetica,sans-Serif" font-size="11.00">/preferences</text>
|
||||
</g>
|
||||
<!-- backend->mock_api -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>backend->mock_api</title>
|
||||
<path fill="none" stroke="black" d="M181.83,-42.54C235.1,-43.08 317.03,-43.92 370.43,-44.46"/>
|
||||
<polygon fill="black" stroke="black" points="370.15,-47.96 380.18,-44.56 370.22,-40.96 370.15,-47.96"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="311.38" y="-47.53" font-family="Helvetica,sans-Serif" font-size="10.00">POST /payments</text>
|
||||
</g>
|
||||
<!-- mock_api->backend -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>mock_api->backend</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M381.55,-32.32C372.93,-30.21 363.86,-28.35 355.25,-27.25 300.78,-20.27 238.48,-25.3 193.1,-31.31"/>
|
||||
<polygon fill="black" stroke="black" points="192.87,-27.8 183.44,-32.64 193.83,-34.74 192.87,-27.8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="311.38" y="-30.5" font-family="Helvetica,sans-Serif" font-size="10.00">webhook callback</text>
|
||||
</g>
|
||||
<!-- state -->
|
||||
<g id="node4" class="node">
|
||||
<title>state</title>
|
||||
<path fill="#ffa726" stroke="black" d="M671.5,-106C671.5,-106 568.5,-106 568.5,-106 562.5,-106 556.5,-100 556.5,-94 556.5,-94 556.5,-82 556.5,-82 556.5,-76 562.5,-70 568.5,-70 568.5,-70 671.5,-70 671.5,-70 677.5,-70 683.5,-76 683.5,-82 683.5,-82 683.5,-94 683.5,-94 683.5,-100 677.5,-106 671.5,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="620" y="-91.05" font-family="Helvetica,sans-Serif" font-size="11.00">State</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="620" y="-77.55" font-family="Helvetica,sans-Serif" font-size="11.00">(pending payments)</text>
|
||||
</g>
|
||||
<!-- mock_api->state -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>mock_api->state</title>
|
||||
<path fill="none" stroke="black" d="M466.91,-54.22C489.66,-59.28 518.54,-65.69 545.01,-71.57"/>
|
||||
<polygon fill="black" stroke="black" points="544.18,-74.97 554.7,-73.72 545.69,-68.14 544.18,-74.97"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="516" y="-72.32" font-family="Helvetica,sans-Serif" font-size="10.00">store</text>
|
||||
</g>
|
||||
<!-- config_ui -->
|
||||
<g id="node3" class="node">
|
||||
<title>config_ui</title>
|
||||
<path fill="#ffb74d" stroke="black" d="M463.5,-123C463.5,-123 385.25,-123 385.25,-123 379.25,-123 373.25,-117 373.25,-111 373.25,-111 373.25,-99 373.25,-99 373.25,-93 379.25,-87 385.25,-87 385.25,-87 463.5,-87 463.5,-87 469.5,-87 475.5,-93 475.5,-99 475.5,-99 475.5,-111 475.5,-111 475.5,-117 469.5,-123 463.5,-123"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="424.38" y="-108.05" font-family="Helvetica,sans-Serif" font-size="11.00">Config UI</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="424.38" y="-94.55" font-family="Helvetica,sans-Serif" font-size="11.00">(set responses)</text>
|
||||
</g>
|
||||
<!-- config_ui->state -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>config_ui->state</title>
|
||||
<path fill="none" stroke="black" d="M475.99,-100.56C496.99,-98.71 521.76,-96.54 544.75,-94.52"/>
|
||||
<polygon fill="black" stroke="black" points="545.05,-98.01 554.7,-93.65 544.44,-91.03 545.05,-98.01"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="516" y="-102.27" font-family="Helvetica,sans-Serif" font-size="10.00">configure</text>
|
||||
</g>
|
||||
<!-- approved -->
|
||||
<g id="node5" class="node">
|
||||
<title>approved</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M839,-160C839,-160 795.25,-160 795.25,-160 789.25,-160 783.25,-154 783.25,-148 783.25,-148 783.25,-136 783.25,-136 783.25,-130 789.25,-124 795.25,-124 795.25,-124 839,-124 839,-124 845,-124 851,-130 851,-136 851,-136 851,-148 851,-148 851,-154 845,-160 839,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="817.12" y="-138.3" font-family="Helvetica,sans-Serif" font-size="11.00">approved</text>
|
||||
</g>
|
||||
<!-- state->approved -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>state->approved</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M682.45,-106.43C692.47,-109.35 702.77,-112.3 712.5,-115 731.93,-120.4 753.5,-126.07 771.91,-130.81"/>
|
||||
<polygon fill="black" stroke="black" points="770.9,-134.17 781.45,-133.26 772.64,-127.38 770.9,-134.17"/>
|
||||
</g>
|
||||
<!-- pending -->
|
||||
<g id="node6" class="node">
|
||||
<title>pending</title>
|
||||
<path fill="#fff9c4" stroke="black" d="M834.88,-106C834.88,-106 799.38,-106 799.38,-106 793.38,-106 787.38,-100 787.38,-94 787.38,-94 787.38,-82 787.38,-82 787.38,-76 793.38,-70 799.38,-70 799.38,-70 834.88,-70 834.88,-70 840.88,-70 846.88,-76 846.88,-82 846.88,-82 846.88,-94 846.88,-94 846.88,-100 840.88,-106 834.88,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="817.12" y="-84.3" font-family="Helvetica,sans-Serif" font-size="11.00">pending</text>
|
||||
</g>
|
||||
<!-- state->pending -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>state->pending</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M683.81,-88C713.99,-88 749.28,-88 775.82,-88"/>
|
||||
<polygon fill="black" stroke="black" points="775.47,-91.5 785.47,-88 775.47,-84.5 775.47,-91.5"/>
|
||||
</g>
|
||||
<!-- rejected -->
|
||||
<g id="node7" class="node">
|
||||
<title>rejected</title>
|
||||
<path fill="#ffcdd2" stroke="black" d="M835.62,-52C835.62,-52 798.62,-52 798.62,-52 792.62,-52 786.62,-46 786.62,-40 786.62,-40 786.62,-28 786.62,-28 786.62,-22 792.62,-16 798.62,-16 798.62,-16 835.62,-16 835.62,-16 841.62,-16 847.62,-22 847.62,-28 847.62,-28 847.62,-40 847.62,-40 847.62,-46 841.62,-52 835.62,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="817.12" y="-30.3" font-family="Helvetica,sans-Serif" font-size="11.00">rejected</text>
|
||||
</g>
|
||||
<!-- state->rejected -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>state->rejected</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M682.45,-69.57C692.47,-66.65 702.77,-63.7 712.5,-61 733.07,-55.29 756.03,-49.27 775.1,-44.37"/>
|
||||
<polygon fill="black" stroke="black" points="775.84,-47.79 784.66,-41.92 774.11,-41.01 775.84,-47.79"/>
|
||||
</g>
|
||||
<!-- real_api -->
|
||||
<g id="node8" class="node">
|
||||
<title>real_api</title>
|
||||
<path fill="#e0e0e0" stroke="black" d="M185.38,-149C185.38,-149 71.12,-149 71.12,-149 65.12,-149 59.12,-143 59.12,-137 59.12,-137 59.12,-125 59.12,-125 59.12,-119 65.12,-113 71.12,-113 71.12,-113 185.38,-113 185.38,-113 191.38,-113 197.38,-119 197.38,-125 197.38,-125 197.38,-137 197.38,-137 197.38,-143 191.38,-149 185.38,-149"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="128.25" y="-127.3" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#9e9e9e">api.mercadopago.com</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.8 KiB |
@@ -1,64 +0,0 @@
|
||||
digraph SlackVein {
|
||||
rankdir=LR;
|
||||
compound=true;
|
||||
fontname="Helvetica";
|
||||
node [fontname="Helvetica", fontsize=11, shape=box, style="rounded,filled"];
|
||||
edge [fontname="Helvetica", fontsize=10];
|
||||
|
||||
labelloc="t";
|
||||
label="Slack Vein - API Flow";
|
||||
fontsize=16;
|
||||
|
||||
// Client
|
||||
subgraph cluster_client {
|
||||
label="Soleprint";
|
||||
style=filled;
|
||||
color="#E8F5E9";
|
||||
fillcolor="#E8F5E9";
|
||||
|
||||
app [label="Application", fillcolor="#C8E6C9"];
|
||||
vein [label="Slack Vein\n(artery/veins/slack)", fillcolor="#A5D6A7"];
|
||||
}
|
||||
|
||||
// Auth
|
||||
subgraph cluster_auth {
|
||||
label="Authentication";
|
||||
style=filled;
|
||||
color="#FFF8E1";
|
||||
fillcolor="#FFF8E1";
|
||||
|
||||
token [label="Bot Token\n(Bearer)", fillcolor="#FFECB3"];
|
||||
}
|
||||
|
||||
// Slack API
|
||||
subgraph cluster_slack {
|
||||
label="Slack API";
|
||||
style=filled;
|
||||
color="#E3F2FD";
|
||||
fillcolor="#E3F2FD";
|
||||
|
||||
chat [label="chat.postMessage", fillcolor="#BBDEFB"];
|
||||
channels [label="conversations.list", fillcolor="#BBDEFB"];
|
||||
users [label="users.list", fillcolor="#BBDEFB"];
|
||||
files [label="files.upload", fillcolor="#BBDEFB"];
|
||||
}
|
||||
|
||||
// Webhooks
|
||||
subgraph cluster_webhooks {
|
||||
label="Incoming";
|
||||
style=dashed;
|
||||
color=gray;
|
||||
|
||||
webhook [label="Webhook URL", fillcolor="#F5F5F5"];
|
||||
}
|
||||
|
||||
// Flow
|
||||
app -> vein [label="send_message()"];
|
||||
vein -> token [label="auth"];
|
||||
token -> chat [label="POST"];
|
||||
token -> channels [label="GET"];
|
||||
token -> users [label="GET"];
|
||||
token -> files [label="POST"];
|
||||
|
||||
vein -> webhook [label="simple post", style=dashed];
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 14.1.1 (0)
|
||||
-->
|
||||
<!-- Title: SlackVein Pages: 1 -->
|
||||
<svg width="746pt" height="294pt"
|
||||
viewBox="0.00 0.00 746.00 294.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 289.5)">
|
||||
<title>SlackVein</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-289.5 741.75,-289.5 741.75,4 -4,4"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="368.88" y="-266.3" font-family="Helvetica,sans-Serif" font-size="16.00">Slack Vein - API Flow</text>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_client</title>
|
||||
<polygon fill="#e8f5e9" stroke="#e8f5e9" points="8,-67 8,-147 340.25,-147 340.25,-67 8,-67"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="174.12" y="-127.8" font-family="Helvetica,sans-Serif" font-size="16.00">Soleprint</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_auth</title>
|
||||
<polygon fill="#fff8e1" stroke="#fff8e1" points="417.25,-104 417.25,-184 551.75,-184 551.75,-104 417.25,-104"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="484.5" y="-164.8" font-family="Helvetica,sans-Serif" font-size="16.00">Authentication</text>
|
||||
</g>
|
||||
<g id="clust3" class="cluster">
|
||||
<title>cluster_slack</title>
|
||||
<polygon fill="#e3f2fd" stroke="#e3f2fd" points="597.25,-8 597.25,-250 729.75,-250 729.75,-8 597.25,-8"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="663.5" y="-230.8" font-family="Helvetica,sans-Serif" font-size="16.00">Slack API</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_webhooks</title>
|
||||
<polygon fill="none" stroke="gray" stroke-dasharray="5,2" points="430.12,-16 430.12,-96 537.88,-96 537.88,-16 430.12,-16"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="484" y="-76.8" font-family="Helvetica,sans-Serif" font-size="16.00">Incoming</text>
|
||||
</g>
|
||||
<!-- app -->
|
||||
<g id="node1" class="node">
|
||||
<title>app</title>
|
||||
<path fill="#c8e6c9" stroke="black" d="M80.75,-111C80.75,-111 28,-111 28,-111 22,-111 16,-105 16,-99 16,-99 16,-87 16,-87 16,-81 22,-75 28,-75 28,-75 80.75,-75 80.75,-75 86.75,-75 92.75,-81 92.75,-87 92.75,-87 92.75,-99 92.75,-99 92.75,-105 86.75,-111 80.75,-111"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="54.38" y="-89.3" font-family="Helvetica,sans-Serif" font-size="11.00">Application</text>
|
||||
</g>
|
||||
<!-- vein -->
|
||||
<g id="node2" class="node">
|
||||
<title>vein</title>
|
||||
<path fill="#a5d6a7" stroke="black" d="M320.25,-111C320.25,-111 221,-111 221,-111 215,-111 209,-105 209,-99 209,-99 209,-87 209,-87 209,-81 215,-75 221,-75 221,-75 320.25,-75 320.25,-75 326.25,-75 332.25,-81 332.25,-87 332.25,-87 332.25,-99 332.25,-99 332.25,-105 326.25,-111 320.25,-111"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="270.62" y="-96.05" font-family="Helvetica,sans-Serif" font-size="11.00">Slack Vein</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="270.62" y="-82.55" font-family="Helvetica,sans-Serif" font-size="11.00">(artery/veins/slack)</text>
|
||||
</g>
|
||||
<!-- app->vein -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>app->vein</title>
|
||||
<path fill="none" stroke="black" d="M93.19,-93C122.02,-93 162.6,-93 197.57,-93"/>
|
||||
<polygon fill="black" stroke="black" points="197.19,-96.5 207.19,-93 197.19,-89.5 197.19,-96.5"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="150.88" y="-96.25" font-family="Helvetica,sans-Serif" font-size="10.00">send_message()</text>
|
||||
</g>
|
||||
<!-- token -->
|
||||
<g id="node3" class="node">
|
||||
<title>token</title>
|
||||
<path fill="#ffecb3" stroke="black" d="M506.62,-148C506.62,-148 461.38,-148 461.38,-148 455.38,-148 449.38,-142 449.38,-136 449.38,-136 449.38,-124 449.38,-124 449.38,-118 455.38,-112 461.38,-112 461.38,-112 506.62,-112 506.62,-112 512.62,-112 518.62,-118 518.62,-124 518.62,-124 518.62,-136 518.62,-136 518.62,-142 512.62,-148 506.62,-148"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="484" y="-133.05" font-family="Helvetica,sans-Serif" font-size="11.00">Bot Token</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="484" y="-119.55" font-family="Helvetica,sans-Serif" font-size="11.00">(Bearer)</text>
|
||||
</g>
|
||||
<!-- vein->token -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>vein->token</title>
|
||||
<path fill="none" stroke="black" d="M332.48,-103.65C366.11,-109.54 407.18,-116.73 437.92,-122.11"/>
|
||||
<polygon fill="black" stroke="black" points="437.21,-125.54 447.67,-123.82 438.42,-118.64 437.21,-125.54"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="378.75" y="-119.15" font-family="Helvetica,sans-Serif" font-size="10.00">auth</text>
|
||||
</g>
|
||||
<!-- webhook -->
|
||||
<g id="node8" class="node">
|
||||
<title>webhook</title>
|
||||
<path fill="#f5f5f5" stroke="black" d="M517.88,-60C517.88,-60 450.12,-60 450.12,-60 444.12,-60 438.12,-54 438.12,-48 438.12,-48 438.12,-36 438.12,-36 438.12,-30 444.12,-24 450.12,-24 450.12,-24 517.88,-24 517.88,-24 523.88,-24 529.88,-30 529.88,-36 529.88,-36 529.88,-48 529.88,-48 529.88,-54 523.88,-60 517.88,-60"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="484" y="-38.3" font-family="Helvetica,sans-Serif" font-size="11.00">Webhook URL</text>
|
||||
</g>
|
||||
<!-- vein->webhook -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>vein->webhook</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M332.48,-78.32C362.09,-71.17 397.46,-62.64 426.47,-55.64"/>
|
||||
<polygon fill="black" stroke="black" points="427.29,-59.04 436.19,-53.29 425.65,-52.24 427.29,-59.04"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="378.75" y="-76.82" font-family="Helvetica,sans-Serif" font-size="10.00">simple post</text>
|
||||
</g>
|
||||
<!-- chat -->
|
||||
<g id="node4" class="node">
|
||||
<title>chat</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M709.75,-214C709.75,-214 617.25,-214 617.25,-214 611.25,-214 605.25,-208 605.25,-202 605.25,-202 605.25,-190 605.25,-190 605.25,-184 611.25,-178 617.25,-178 617.25,-178 709.75,-178 709.75,-178 715.75,-178 721.75,-184 721.75,-190 721.75,-190 721.75,-202 721.75,-202 721.75,-208 715.75,-214 709.75,-214"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="663.5" y="-192.3" font-family="Helvetica,sans-Serif" font-size="11.00">chat.postMessage</text>
|
||||
</g>
|
||||
<!-- token->chat -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>token->chat</title>
|
||||
<path fill="none" stroke="black" d="M518.8,-142.57C542.44,-151.36 574.65,-163.33 602.58,-173.72"/>
|
||||
<polygon fill="black" stroke="black" points="601.04,-176.88 611.63,-177.09 603.48,-170.32 601.04,-176.88"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="574.5" y="-170.2" font-family="Helvetica,sans-Serif" font-size="10.00">POST</text>
|
||||
</g>
|
||||
<!-- channels -->
|
||||
<g id="node5" class="node">
|
||||
<title>channels</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M708.25,-160C708.25,-160 618.75,-160 618.75,-160 612.75,-160 606.75,-154 606.75,-148 606.75,-148 606.75,-136 606.75,-136 606.75,-130 612.75,-124 618.75,-124 618.75,-124 708.25,-124 708.25,-124 714.25,-124 720.25,-130 720.25,-136 720.25,-136 720.25,-148 720.25,-148 720.25,-154 714.25,-160 708.25,-160"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="663.5" y="-138.3" font-family="Helvetica,sans-Serif" font-size="11.00">conversations.list</text>
|
||||
</g>
|
||||
<!-- token->channels -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>token->channels</title>
|
||||
<path fill="none" stroke="black" d="M518.8,-132.29C540.36,-133.74 569.04,-135.68 595.11,-137.44"/>
|
||||
<polygon fill="black" stroke="black" points="594.76,-140.93 604.97,-138.11 595.23,-133.94 594.76,-140.93"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="574.5" y="-139.97" font-family="Helvetica,sans-Serif" font-size="10.00">GET</text>
|
||||
</g>
|
||||
<!-- users -->
|
||||
<g id="node6" class="node">
|
||||
<title>users</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M684.62,-106C684.62,-106 642.38,-106 642.38,-106 636.38,-106 630.38,-100 630.38,-94 630.38,-94 630.38,-82 630.38,-82 630.38,-76 636.38,-70 642.38,-70 642.38,-70 684.62,-70 684.62,-70 690.62,-70 696.62,-76 696.62,-82 696.62,-82 696.62,-94 696.62,-94 696.62,-100 690.62,-106 684.62,-106"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="663.5" y="-84.3" font-family="Helvetica,sans-Serif" font-size="11.00">users.list</text>
|
||||
</g>
|
||||
<!-- token->users -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>token->users</title>
|
||||
<path fill="none" stroke="black" d="M518.8,-122C547.29,-115.26 588.23,-105.57 619.13,-98.26"/>
|
||||
<polygon fill="black" stroke="black" points="619.62,-101.74 628.55,-96.03 618.01,-94.93 619.62,-101.74"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="574.5" y="-114.76" font-family="Helvetica,sans-Serif" font-size="10.00">GET</text>
|
||||
</g>
|
||||
<!-- files -->
|
||||
<g id="node7" class="node">
|
||||
<title>files</title>
|
||||
<path fill="#bbdefb" stroke="black" d="M691,-52C691,-52 636,-52 636,-52 630,-52 624,-46 624,-40 624,-40 624,-28 624,-28 624,-22 630,-16 636,-16 636,-16 691,-16 691,-16 697,-16 703,-22 703,-28 703,-28 703,-40 703,-40 703,-46 697,-52 691,-52"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="663.5" y="-30.3" font-family="Helvetica,sans-Serif" font-size="11.00">files.upload</text>
|
||||
</g>
|
||||
<!-- token->files -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>token->files</title>
|
||||
<path fill="none" stroke="black" d="M519.01,-117.82C529.97,-113.1 541.84,-107.11 551.75,-100 557.05,-96.2 556.96,-93.68 561.75,-89.25 576.55,-75.55 579.88,-71.23 597.25,-61 602.4,-57.97 607.95,-55.11 613.57,-52.47"/>
|
||||
<polygon fill="black" stroke="black" points="614.59,-55.85 622.3,-48.59 611.74,-49.46 614.59,-55.85"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="574.5" y="-92.5" font-family="Helvetica,sans-Serif" font-size="10.00">POST</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.4 KiB |
56
docs/viewer.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Graph | soleprint</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; }
|
||||
body { background: #0a0a0a; overflow: hidden; width: 100vw; height: 100vh; }
|
||||
#container { width: 100vw; height: 100vh; overflow: hidden; cursor: grab; }
|
||||
#container.dragging { cursor: grabbing; }
|
||||
img { transform-origin: 0 0; user-select: none; -webkit-user-drag: none; }
|
||||
.back { position: fixed; top: 1rem; left: 1rem; color: #d4a574; text-decoration: none; font-family: system-ui; font-size: 0.85rem; z-index: 10; }
|
||||
.back:hover { text-decoration: underline; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a class="back" href="index.html">← docs</a>
|
||||
<div id="container"><img id="img"></div>
|
||||
<script>
|
||||
var src = new URLSearchParams(location.search).get('src');
|
||||
var img = document.getElementById('img');
|
||||
var container = document.getElementById('container');
|
||||
img.src = src;
|
||||
var scale = 1, x = 0, y = 0, dragging = false, startX, startY, startPanX, startPanY;
|
||||
function apply() { img.style.transform = 'translate(' + x + 'px,' + y + 'px) scale(' + scale + ')'; }
|
||||
img.onload = function() {
|
||||
var sw = window.innerWidth / img.naturalWidth;
|
||||
var sh = window.innerHeight / img.naturalHeight;
|
||||
scale = Math.min(sw, sh) * 0.9;
|
||||
x = (window.innerWidth - img.naturalWidth * scale) / 2;
|
||||
y = (window.innerHeight - img.naturalHeight * scale) / 2;
|
||||
apply();
|
||||
};
|
||||
container.addEventListener('wheel', function(e) {
|
||||
e.preventDefault();
|
||||
var factor = e.deltaY < 0 ? 1.12 : 0.89;
|
||||
var rect = container.getBoundingClientRect();
|
||||
var mx = e.clientX - rect.left, my = e.clientY - rect.top;
|
||||
x = mx - (mx - x) * factor; y = my - (my - y) * factor;
|
||||
scale *= factor; apply();
|
||||
}, { passive: false });
|
||||
container.addEventListener('mousedown', function(e) {
|
||||
if (e.button !== 0) return;
|
||||
dragging = true; startX = e.clientX; startY = e.clientY;
|
||||
startPanX = x; startPanY = y;
|
||||
container.classList.add('dragging'); e.preventDefault();
|
||||
});
|
||||
window.addEventListener('mousemove', function(e) {
|
||||
if (!dragging) return;
|
||||
x = startPanX + (e.clientX - startX); y = startPanY + (e.clientY - startY); apply();
|
||||
});
|
||||
window.addEventListener('mouseup', function() { dragging = false; container.classList.remove('dragging'); });
|
||||
container.addEventListener('dblclick', function() { img.onload(); });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||