diff --git a/docs/architecture/01-system-overview.dot b/docs/architecture/01-system-overview.dot new file mode 100644 index 0000000..7bb61b1 --- /dev/null +++ b/docs/architecture/01-system-overview.dot @@ -0,0 +1,102 @@ +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]; +} diff --git a/docs/architecture/01-system-overview.svg b/docs/architecture/01-system-overview.svg new file mode 100644 index 0000000..5804b61 --- /dev/null +++ b/docs/architecture/01-system-overview.svg @@ -0,0 +1,244 @@ + + + + + + +SystemOverview + +Soleprint - System Overview + +cluster_soleprint + +Soleprint Hub (port 12000) + + +cluster_artery + +Artery - Todo lo vital + + +cluster_atlas + +Atlas - Documentacion accionable + + +cluster_station + +Station - Centro de control + + +cluster_external + +External Services + + +cluster_room + +Managed Room (e.g., AMAR) + + + +hub + +Soleprint +Core Coordinator + + + +veins + +Veins +(Stateless Connectors) + + + +hub->veins + + +routes + + + +books + +Books +(Documentation) + + + +hub->books + + +routes + + + +tools + +Tools +(modelgen, tester, datagen) + + + +hub->tools + + +routes + + + +pulses + +Pulses +(Composed Flows) + + + +veins->pulses + + +compose + + + +jira + +Jira + + + +veins->jira + + +API + + + +slack + +Slack + + + +veins->slack + + +API + + + +google + +Google + + + +veins->google + + +OAuth + + + +shunts + +Shunts +(Mock Connectors) + + + +mercadopago + +MercadoPago + + + +shunts->mercadopago + + +mock + + + +plexus + +Plexus +(Full Apps) + + + +pulses->plexus + + +extend + + + +templates + +Templates +(Patterns) + + + +depots + +Depots +(External Docs) + + + +room_backend + +Backend +(Django/FastAPI) + + + +depots->room_backend + + +docs + + + +tools->room_backend + + +test + + + +monitors + +Monitors +(databrowse) + + + +room_db + + +Database +(PostgreSQL) + + + +monitors->room_db + + +browse + + + +room_frontend + +Frontend +(Next.js) + + + diff --git a/docs/architecture/02-artery-hierarchy.dot b/docs/architecture/02-artery-hierarchy.dot new file mode 100644 index 0000000..5eabaf3 --- /dev/null +++ b/docs/architecture/02-artery-hierarchy.dot @@ -0,0 +1,86 @@ +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=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeStateFrontendDeploy
VeinNone (or OAuth)Optional test UIWith soleprint
ShuntConfigurableConfig UIWith soleprint
PulseVein + configUses vein'sWith soleprint
PlexusFull app stateRequiredSelf-contained
+ >]; + } +} diff --git a/docs/architecture/02-artery-hierarchy.svg b/docs/architecture/02-artery-hierarchy.svg new file mode 100644 index 0000000..5a479b1 --- /dev/null +++ b/docs/architecture/02-artery-hierarchy.svg @@ -0,0 +1,134 @@ + + + + + + +ArteryHierarchy + +Artery - Connector Hierarchy + +cluster_main + +Evolution Path + + +cluster_mock + +Testing Path + + +cluster_props + +Properties + + + +vein + +Vein +Stateless API connector +e.g., Jira, Slack, Google + + + +pulse + +Pulse +Vein + Room + Depot +e.g., Jira for AMAR project + + + +vein->pulse + + ++ Room ++ Depot + + + +shunt + +Shunt +Fake connector for testing +e.g., mercadopago mock + + + +vein->shunt + + +mock + + + +plexus + +Plexus +Full app: backend + frontend + DB +e.g., WhatsApp with chat UI + + + +pulse->plexus + + ++ Backend ++ Frontend ++ DB + + + +props + + + +Type + + +State + + +Frontend + + +Deploy + +Vein + +None (or OAuth) + +Optional test UI + +With soleprint + +Shunt + +Configurable + +Config UI + +With soleprint + +Pulse + +Vein + config + +Uses vein's + +With soleprint + +Plexus + +Full app state + +Required + +Self-contained + + + diff --git a/docs/architecture/03-build-flow.dot b/docs/architecture/03-build-flow.dot new file mode 100644 index 0000000..c7ec9cd --- /dev/null +++ b/docs/architecture/03-build-flow.dot @@ -0,0 +1,85 @@ +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//\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]; +} diff --git a/docs/architecture/03-build-flow.svg b/docs/architecture/03-build-flow.svg new file mode 100644 index 0000000..5a960ba --- /dev/null +++ b/docs/architecture/03-build-flow.svg @@ -0,0 +1,190 @@ + + + + + + +BuildFlow + +Soleprint - Build Flow + +cluster_source + +Source (spr/) + + +cluster_cfg + +Room Configs (cfg/) + + +cluster_cmds + +Commands + + +cluster_gen + +Generated Output (gen/) + + + +soleprint_src + +soleprint/ +(core entry points) + + + +build + +build.py + + + +soleprint_src->build + + + + + +artery_src + +artery/ +(veins, shunts) + + + +artery_src->build + + + + + +atlas_src + +atlas/ +(books) + + + +atlas_src->build + + + + + +station_src + +station/ +(tools, monitors) + + + +station_src->build + + + + + +cfg_standalone + +cfg/standalone/ +config.json +data/ + + + +cfg_standalone->build + + + + + +cfg_amar + +cfg/amar/ +config.json +data/ +docker-compose.yml +... + + + +cfg_amar->build + + + + + +cfg_other + +cfg/<room>/ +... + + + +cmd1 + +python build.py dev + + + + +cmd2 + +python build.py dev --cfg amar + + + + +cmd3 + +python build.py dev --all + + + + +gen_standalone + +gen/standalone/ +(base soleprint) + + + +cmd1->gen_standalone + + +copies + standalone config + + + +gen_amar + +gen/amar/ +(with amar config) + + + +cmd2->gen_amar + + +copies + amar config + + + +cmd3->gen_standalone + + + + + +cmd3->gen_amar + + + + + diff --git a/docs/architecture/04-room-config.dot b/docs/architecture/04-room-config.dot new file mode 100644 index 0000000..797fd73 --- /dev/null +++ b/docs/architecture/04-room-config.dot @@ -0,0 +1,83 @@ +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//"; + 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"]; + } +} diff --git a/docs/architecture/04-room-config.svg b/docs/architecture/04-room-config.svg new file mode 100644 index 0000000..9b6f60e --- /dev/null +++ b/docs/architecture/04-room-config.svg @@ -0,0 +1,161 @@ + + + + + + +RoomConfig + +Soleprint - Room Configuration Structure + +cluster_room + +cfg/<room>/ + + +cluster_data + +data/ + + +cluster_docker + +Docker + + +cluster_soleprint + +soleprint/ + + +cluster_extras + +Room-specific + + +cluster_examples + +Examples + + + +config_json + +config.json +Framework branding +Terminology customization +(can rebrand soleprint) + + + +veins_json + +veins.json + + + +shunts_json + +shunts.json + + + +depots_json + +depots.json + + + +rooms_json + +rooms.json + + + +docker_compose + +docker-compose.yml + + + +dockerfile_be + +Dockerfile.backend + + + +dockerfile_fe + +Dockerfile.frontend + + + +env_example + +.env.example + + + +spr_compose + +docker-compose.yml +(soleprint for this room) + + + +spr_env + +.env + + + +databrowse + +databrowse/depot/ +(DB schema) + + + +tester + +tester/tests/ +(Room tests) + + + +monitors + +monitors/ +(Room monitors) + + + +models + +models/ +(Room models) + + + +standalone + +cfg/standalone/ +Base soleprint +Generic veins +No docker-compose + + + +amar + +cfg/amar/ +AMAR veterinary app +amar + mercadopago shunts +Full Docker setup +Custom monitors (turnos) + + + diff --git a/docs/architecture/graph.html b/docs/architecture/graph.html new file mode 100644 index 0000000..0a1491a --- /dev/null +++ b/docs/architecture/graph.html @@ -0,0 +1,115 @@ + + + + + + Graph Viewer - Soleprint + + + +
+ ← Back + +

Loading...

+
+ + + + + +
+
+ +
+ Graph +
+ + + + diff --git a/docs/architecture/index.html b/docs/architecture/index.html new file mode 100644 index 0000000..447b3c6 --- /dev/null +++ b/docs/architecture/index.html @@ -0,0 +1,206 @@ + + + + + + Soleprint - Architecture + + + +
+

Soleprint

+

Cada paso deja huella / Each step leaves a mark

+
+ +
+ +
+

What Soleprint Solves

+
+
+

Freelance Work Standardization

+

Generalizing and homogenizing freelance work across projects. Instead of setting up different environments, testing approaches, and connector patterns for each client, Soleprint provides a consistent framework. Build once, reuse everywhere.

+
+
+

Missing Infrastructure Replication

+

When working with large corps where you can't access their Jira, Slack, payment systems, or internal APIs directly - Soleprint's shunts let you mock those systems locally. Test against fake MercadoPago, fake Jira tickets, fake webhooks without needing real credentials.

+
+
+

Reliable Testing Environment

+

Figure out what tests to write by actually running flows in a controlled environment. BDD -> Gherkin -> Tests workflow. Instead of guessing what to test, you explore the actual behavior first, document it, then generate tests from that documentation.

+
+
+
+ + +
+
+

System Overview

+ View Full +
+ + System Overview + +
+

The four systems that make up Soleprint.

+

Systems

+
    +
  • Soleprint: Core coordinator hub (port 12000)
  • +
  • Artery: Connectors to external services - "Todo lo vital"
  • +
  • Atlas: Actionable documentation - "Documentacion accionable"
  • +
  • Station: Tools and monitors - "Centro de control"
  • +
+
+
+ + +
+
+

Artery Hierarchy

+ View Full +
+ + Artery Hierarchy + +
+

How connectors evolve from simple to complex.

+

Connector Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescriptionExample
VeinStateless API connectorJira, Slack, Google
ShuntFake connector for testingMercadoPago mock
PulseVein + Room + DepotJira for AMAR project
PlexusFull app (backend + frontend + DB)WhatsApp with chat UI
+
+
+ + +
+
+

Build Flow

+ View Full +
+ + Build Flow + +
+

How source is built into runnable instances.

+

Commands

+ + + + + + + + + + + + + + + + + + + + + +
CommandOutput
python build.py devgen/standalone/
python build.py dev --cfg amargen/amar/
python build.py dev --allboth
+
+
+ + +
+
+

Room Configuration

+ View Full +
+ + Room Configuration + +
+

How rooms are configured in cfg/.

+

Room Structure

+
    +
  • config.json: Framework branding, terminology
  • +
  • data/: veins.json, shunts.json, depots.json
  • +
  • soleprint/: Docker config for this room
  • +
  • databrowse/, tester/, monitors/, models/: Room-specific extensions
  • +
+
+
+ + +
+

Technology Stack

+
+
+

Core

+
    +
  • Python 3.11+
  • +
  • FastAPI
  • +
  • Jinja2
  • +
+
+
+

Tools

+
    +
  • modelgen
  • +
  • tester (Playwright)
  • +
  • datagen
  • +
  • databrowse
  • +
+
+
+

Veins

+
    +
  • Jira
  • +
  • Slack
  • +
  • Google (OAuth)
  • +
+
+
+

Infrastructure

+
    +
  • Docker
  • +
  • Woodpecker CI
  • +
  • Nginx
  • +
+
+
+
+
+ +
+

Soleprint - Development Workflow Platform

+

Generated:

+
+ + diff --git a/docs/architecture/styles.css b/docs/architecture/styles.css new file mode 100644 index 0000000..4f251b9 --- /dev/null +++ b/docs/architecture/styles.css @@ -0,0 +1,343 @@ +:root { + --bg-primary: #1a1a2e; + --bg-secondary: #16213e; + --bg-card: #0f3460; + --text-primary: #eee; + --text-secondary: #a0a0a0; + --accent: #e94560; + --accent-secondary: #533483; + --border: #2a2a4a; +} + +* { + 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; +} diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..59e0248 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,70 @@ + + + + + + Soleprint - Documentation + + + +
+

Soleprint

+

Cada paso deja huella / Each step leaves a mark

+
+ +
+
+

Documentation

+ +
+ +
+

Quick Start

+
+

Build & Run

+
+# Build standalone
+python build.py dev
+cd gen/standalone && .venv/bin/python run.py
+
+# Build with room config
+python build.py dev --cfg amar
+cd gen/amar && .venv/bin/python run.py
+
+# Visit http://localhost:12000
+
+
+ +
+

What Soleprint Solves

+
+
+

Freelance Work Standardization

+

Consistent framework across projects. Build once, reuse everywhere.

+
+
+

Missing Infrastructure

+

Mock external systems locally when you can't access client infrastructure.

+
+
+

Testing Environment

+

BDD -> Gherkin -> Tests. Explore behavior first, then generate tests.

+
+
+
+
+ +
+

Soleprint - Development Workflow Platform

+
+ + diff --git a/docs/veins/google.dot b/docs/veins/google.dot new file mode 100644 index 0000000..f41c9cc --- /dev/null +++ b/docs/veins/google.dot @@ -0,0 +1,61 @@ +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"]; +} diff --git a/docs/veins/google.svg b/docs/veins/google.svg new file mode 100644 index 0000000..f0818c4 --- /dev/null +++ b/docs/veins/google.svg @@ -0,0 +1,158 @@ + + + + + + +GoogleVein + +Google Vein - OAuth Flow + +cluster_client + +Soleprint + + +cluster_oauth + +OAuth 2.0 + + +cluster_google + +Google APIs + + + +app + +Application + + + +vein + +Google Vein +(artery/veins/google) + + + +app->vein + + +get_sheets() + + + +oauth + +OAuth Handler +(artery/oauth.py) + + + +vein->oauth + + +ensure_auth + + + +auth_url + +1. Authorization URL + + + +oauth->auth_url + + + + + +sheets + +Sheets API + + + +oauth->sheets + + +Bearer token + + + +calendar + +Calendar API + + + +oauth->calendar + + +Bearer token + + + +drive + +Drive API + + + +oauth->drive + + +Bearer token + + + +consent + +2. User Consent + + + +auth_url->consent + + + + + +callback + +3. Callback + Code + + + +consent->callback + + + + + +tokens + +4. Access + Refresh +Tokens + + + +callback->tokens + + + + + +tokens->oauth + + +store + + + diff --git a/docs/veins/graph.html b/docs/veins/graph.html new file mode 100644 index 0000000..539de6a --- /dev/null +++ b/docs/veins/graph.html @@ -0,0 +1,115 @@ + + + + + + Graph Viewer - Veins + + + +
+ ← Back + +

Loading...

+
+ + + + + +
+
+ +
+ Graph +
+ + + + diff --git a/docs/veins/index.html b/docs/veins/index.html new file mode 100644 index 0000000..4770a6b --- /dev/null +++ b/docs/veins/index.html @@ -0,0 +1,172 @@ + + + + + + Veins & Shunts - Soleprint + + + +
+

Veins & Shunts

+

API Connectors & Mock Services

+
+ +
+
+

← Back to Docs

+
+ + +
+

Veins (Stateless API Connectors)

+

+ Veins are stateless connectors to external APIs. They handle authentication and provide a clean interface for the rest of the application. +

+
+ +
+
+

Jira

+ View Full +
+ + Jira Vein + +
+

Connect to Jira Cloud for issue tracking.

+

Capabilities

+
    +
  • Get/create/update issues
  • +
  • JQL search
  • +
  • Transition issues between statuses
  • +
  • List projects
  • +
+

Auth

+

API Token (Basic Auth with email + token)

+
+
+ +
+
+

Slack

+ View Full +
+ + Slack Vein + +
+

Send messages and interact with Slack workspaces.

+

Capabilities

+
    +
  • Post messages to channels
  • +
  • List channels and users
  • +
  • Upload files
  • +
  • Webhook integration
  • +
+

Auth

+

Bot Token (Bearer)

+
+
+ +
+
+

Google

+ View Full +
+ + Google Vein + +
+

Access Google Sheets, Calendar, Drive via OAuth 2.0.

+

Capabilities

+
    +
  • Read/write Sheets
  • +
  • Calendar events
  • +
  • Drive file access
  • +
+

Auth

+

OAuth 2.0 with refresh tokens

+
+
+ + +
+

Shunts (Mock Connectors)

+

+ 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. +

+
+ +
+
+

MercadoPago Shunt

+ View Full +
+ + MercadoPago Shunt + +
+

Mock MercadoPago payment API for testing payment flows.

+

Features

+
    +
  • Fake payment creation
  • +
  • Configurable responses (approved/pending/rejected)
  • +
  • Webhook callbacks
  • +
  • Config UI to set next response
  • +
+

Use Case

+

Test checkout flows without real payments. Set the shunt to return "approved" or "rejected" and verify your app handles each case.

+
+
+ + +
+

Vein Pattern

+
+
+

Structure

+
    +
  • artery/veins/{name}/
  • +
  • __init__.py (exports)
  • +
  • client.py (API client)
  • +
  • models.py (types)
  • +
  • templates/ (test UI)
  • +
+
+
+

Base Class

+
    +
  • Extends artery/veins/base.py
  • +
  • Common auth handling
  • +
  • Request/response logging
  • +
  • Error handling
  • +
+
+
+

OAuth

+
    +
  • artery/oauth.py
  • +
  • Token storage
  • +
  • Refresh flow
  • +
  • Callback handling
  • +
+
+
+

Config

+
    +
  • cfg/{room}/data/veins.json
  • +
  • Per-room credentials
  • +
  • Enable/disable veins
  • +
+
+
+
+
+ +
+

Soleprint - Veins & Shunts Documentation

+
+ + diff --git a/docs/veins/jira.dot b/docs/veins/jira.dot new file mode 100644 index 0000000..71d0baa --- /dev/null +++ b/docs/veins/jira.dot @@ -0,0 +1,53 @@ +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"]; +} diff --git a/docs/veins/jira.svg b/docs/veins/jira.svg new file mode 100644 index 0000000..dda834d --- /dev/null +++ b/docs/veins/jira.svg @@ -0,0 +1,115 @@ + + + + + + +JiraVein + +Jira Vein - API Flow + +cluster_client + +Soleprint + + +cluster_auth + +Authentication + + +cluster_jira + +Jira Cloud API + + + +app + +Application + + + +vein + +Jira Vein +(artery/veins/jira) + + + +app->vein + + +get_issue() + + + +token + +API Token +(Basic Auth) + + + +vein->token + + +auth + + + +issues + +/rest/api/3/issue + + + +token->issues + + +GET/POST + + + +search + +/rest/api/3/search + + + +token->search + + +JQL + + + +projects + +/rest/api/3/project + + + +token->projects + + +list + + + +transitions + +/rest/api/3/issue/{id}/transitions + + + +token->transitions + + +update status + + + diff --git a/docs/veins/mercadopago-shunt.dot b/docs/veins/mercadopago-shunt.dot new file mode 100644 index 0000000..7d6d189 --- /dev/null +++ b/docs/veins/mercadopago-shunt.dot @@ -0,0 +1,64 @@ +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]; +} diff --git a/docs/veins/mercadopago-shunt.svg b/docs/veins/mercadopago-shunt.svg new file mode 100644 index 0000000..dddb562 --- /dev/null +++ b/docs/veins/mercadopago-shunt.svg @@ -0,0 +1,133 @@ + + + + + + +MercadoPagoShunt + +MercadoPago Shunt - Mock Payment Flow + +cluster_client + +Managed Room (e.g., AMAR) + + +cluster_shunt + +Shunt (artery/shunts/mercadopago) + + +cluster_responses + +Configurable Responses + + +cluster_real + +Real MercadoPago (bypassed) + + + +backend + +Backend +(Django/FastAPI) + + + +mock_api + +Mock API +/payments +/preferences + + + +backend->mock_api + + +POST /payments + + + +mock_api->backend + + +webhook callback + + + +state + +State +(pending payments) + + + +mock_api->state + + +store + + + +config_ui + +Config UI +(set responses) + + + +config_ui->state + + +configure + + + +approved + +approved + + + +state->approved + + + + + +pending + +pending + + + +state->pending + + + + + +rejected + +rejected + + + +state->rejected + + + + + +real_api + +api.mercadopago.com + + + diff --git a/docs/veins/slack.dot b/docs/veins/slack.dot new file mode 100644 index 0000000..478e1d3 --- /dev/null +++ b/docs/veins/slack.dot @@ -0,0 +1,64 @@ +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]; +} diff --git a/docs/veins/slack.svg b/docs/veins/slack.svg new file mode 100644 index 0000000..c3d94c4 --- /dev/null +++ b/docs/veins/slack.svg @@ -0,0 +1,133 @@ + + + + + + +SlackVein + +Slack Vein - API Flow + +cluster_client + +Soleprint + + +cluster_auth + +Authentication + + +cluster_slack + +Slack API + + +cluster_webhooks + +Incoming + + + +app + +Application + + + +vein + +Slack Vein +(artery/veins/slack) + + + +app->vein + + +send_message() + + + +token + +Bot Token +(Bearer) + + + +vein->token + + +auth + + + +webhook + +Webhook URL + + + +vein->webhook + + +simple post + + + +chat + +chat.postMessage + + + +token->chat + + +POST + + + +channels + +conversations.list + + + +token->channels + + +GET + + + +users + +users.list + + + +token->users + + +GET + + + +files + +files.upload + + + +token->files + + +POST + + +