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=<
+
+
+ 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/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
+
+
+
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
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"
+
+
+
+
+
+
+
+
+
+
+
+
How connectors evolve from simple to complex.
+
Connector Types
+
+
+
+ Type
+ Description
+ Example
+
+
+
+
+ Vein
+ Stateless API connector
+ Jira, Slack, Google
+
+
+ Shunt
+ Fake connector for testing
+ MercadoPago mock
+
+
+ Pulse
+ Vein + Room + Depot
+ Jira for AMAR project
+
+
+ Plexus
+ Full app (backend + frontend + DB)
+ WhatsApp with chat UI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
How source is built into runnable instances.
+
Commands
+
+
+
+ Command
+ Output
+
+
+
+
+ python build.py dev
+ gen/standalone/
+
+
+ python build.py dev --cfg amar
+ gen/amar/
+
+
+ python build.py dev --all
+ both
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+
+
+
+
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 (Stateless API Connectors)
+
+ Veins are stateless connectors to external APIs. They handle authentication and provide a clean interface for the rest of the application.
+
+
+
+
+
+
+
+
+
+
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)
+
+
+
+
+
+
+
+
+
+
Send messages and interact with Slack workspaces.
+
Capabilities
+
+ Post messages to channels
+ List channels and users
+ Upload files
+ Webhook integration
+
+
Auth
+
Bot Token (Bearer)
+
+
+
+
+
+
+
+
+
+
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.
+
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+
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
+
+
+