breznflow/README.md
Michael 066414724b release: v1.0.2
- Fix WordPress.org plugin review issues (nonce verification, input sanitization, output escaping)
- Embed page uses wp_enqueue_style/wp_enqueue_script with wp_head/wp_footer
- Update plugin author to NoSchmarrn.dev
- Shorten readme.txt short description to ≤150 chars
- Add GitHub Actions release workflow
- Add .gitignore
2026-04-14 11:21:48 +00:00

358 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BreznFlow
![PHP 8.0+](https://img.shields.io/badge/PHP-8.0%2B-blue)
![WordPress 6.0+](https://img.shields.io/badge/WordPress-6.0%2B-21759b)
![License: GPL-2.0](https://img.shields.io/badge/License-GPL--2.0--or--later-green)
![Version](https://img.shields.io/badge/Version-1.0.2-orange)
🇩🇪 [Deutsche Version → README.de.md](README.de.md)
---
BreznFlow is a WordPress plugin that renders n8n automation workflows as interactive SVG diagrams — directly in posts and pages. Paste your workflow JSON, and the plugin turns it into a zoomable, clickable diagram with node detail panels, sensitive data masking, and brand-colored node icons.
No external dependencies. No CDN. No tracking. Vanilla JavaScript. One shortcode: `[breznflow id="X"]`.
---
## Why This Plugin Exists
n8n workflows are powerful, but sharing them visually is surprisingly hard. Screenshots are static and get outdated. Embedding the n8n editor is impractical. Copy-pasting JSON into a blog post is unreadable.
BreznFlow solves this by turning the raw JSON export into an interactive diagram — the same nodes, the same connections, but rendered as a clean SVG inside WordPress. Readers can zoom, pan, and click any node to inspect its parameters.
Built in Passau, Bavaria — for [mifupa.com](https://mifupa.com), a personal blog where n8n automations are documented regularly and needed a better way to be presented.
---
## Table of Contents
- [Why This Plugin Exists](#why-this-plugin-exists)
- [Directory Structure](#directory-structure)
- [Features](#features)
- [Data Storage](#data-storage)
- [Security](#security)
- [Shortcode](#shortcode)
- [Installation](#installation)
- [Tech Stack](#tech-stack)
- [License](#license)
---
## Directory Structure
```
breznflow/
├── breznflow.php # Plugin header, constants (BREZNFLOW_VERSION, BREZNFLOW_DIR, BREZNFLOW_URL)
├── uninstall.php # Cleanup on plugin deletion
├── readme.txt # WordPress.org plugin readme
├── assets/
│ ├── admin.css # Admin stylesheet (wizard, settings, list table)
│ ├── admin.js # Admin JavaScript (wizard steps, JSON validation)
│ ├── renderer.css # Frontend SVG renderer styles
│ ├── renderer.js # Frontend renderer (SVG engine, pan/zoom, detail panel)
│ ├── brezn.css # Legacy Brezn theme (compat)
│ └── themes/
│ ├── dark.css # Dark theme (default)
│ ├── light.css # Light theme
│ ├── minimal.css # Minimal theme
│ ├── tech.css # Tech theme
│ └── brezn.css # Brezn theme
├── includes/
│ ├── Core.php # Singleton bootstrap, loads all dependencies
│ ├── PostType.php # CPT breznflow_workflow + taxonomy breznflow_category
│ ├── Shortcode.php # [breznflow] shortcode with 13 attributes
│ ├── DownloadHandler.php # JSON download endpoint (?breznflow_download={id})
│ ├── EmbedHandler.php # Standalone embed page (?breznflow_embed={id})
│ ├── Admin/
│ │ ├── AdminMenu.php # Menu structure + dashboard render
│ │ ├── SettingsPage.php # Plugin settings (16 options, validated)
│ │ ├── ThemesPage.php # Theme management (import/delete custom themes)
│ │ ├── WizardPage.php # 3-step import wizard (paste/upload → configure → preview)
│ │ ├── WorkflowListTable.php # WP_List_Table for workflow management
│ │ └── views/ # PHP templates for all admin pages
│ ├── Features/
│ │ ├── NodeTypeRegistry.php # 86 node types with brand colors and icons
│ │ ├── NodeCategorizer.php # Categorizes nodes (trigger, action, logic, AI, etc.)
│ │ ├── InfoBoxBuilder.php # "3× HTTP Request, 2× Code" node summary
│ │ ├── ViewCounter.php # Per-workflow view counting
│ │ ├── RelatedWorkflows.php # Related workflows by shared node types
│ │ ├── ThemeRegistry.php # 5 built-in themes + custom theme support
│ │ └── ThemeImporter.php # Import/export .breznflow.json theme files
│ └── Security/
│ ├── MaskingRules.php # Secret detection patterns (URL params, headers, entropy)
│ ├── WorkflowValidator.php # JSON schema validation for n8n exports
│ └── WorkflowSanitizer.php # Two-pass sanitization: strings + secret masking
└── languages/
├── breznflow.pot # Translation template
├── breznflow-de_DE.po # German translation
└── breznflow-de_DE.mo # Compiled German translation
```
---
## Features
### Interactive SVG Renderer
The core of BreznFlow. Every n8n node becomes a clickable SVG element with brand-colored icons, connection lines, and labels. The renderer supports:
- **Pan & zoom** — mouse wheel zooms to cursor position, click-drag to pan
- **Node click** — opens the detail panel below the diagram with all node parameters
- **Auto-fit** — workflows exceeding a configurable node threshold (default: 30) automatically zoom to the trigger node on load
- **Minimap** — optional minimap overlay for navigation in large workflows
- **Fullscreen** — portal-based fullscreen mode
All rendering happens client-side in vanilla JavaScript — no canvas, no WebGL, no external libraries.
---
### 3-Step Import Wizard
1. **Paste or upload** — paste JSON directly, upload a `.json` file, or fetch from URL
2. **Configure** — set display mode, theme, zoom level, title, categories
3. **Preview** — live SVG preview with security masking summary before publishing
The wizard validates JSON against the n8n schema, sanitizes all strings, and masks detected secrets. The masking log shows exactly what was redacted and why.
**Import from URL:** Fetches workflow JSON from any public URL using `wp_remote_get()`. Requests to private/internal network addresses (localhost, LAN ranges, cloud metadata endpoints) are blocked.
---
### Node Type Registry
86 predefined node types with brand-accurate colors and 2-letter icons:
| Category | Examples |
|---|---|
| Triggers | Schedule, Webhook, Manual, Form |
| Core Logic | HTTP Request, Code, IF, Switch, Merge, Filter |
| Data Transformation | HTML, XML, Markdown, Crypto |
| Databases | MySQL, PostgreSQL, Redis, MongoDB, SQLite, Supabase |
| Communication | Slack, Telegram, Discord, Gmail, WhatsApp |
| Google | Sheets, Drive, Calendar, Docs, YouTube |
| Dev Tools | GitHub, GitLab, Jira, Confluence, Linear, Notion |
| AI | OpenAI, Claude, Gemini, Ollama, Hugging Face, Mistral, LangChain |
| Storage | FTP, SSH, Airtable, Baserow |
| CRM/Marketing | HubSpot, Salesforce, Mailchimp, Brevo |
Unknown node types get a deterministic fallback: 2-letter initials, and a color derived from a djb2 hash — so the same unknown type always looks the same.
---
### Theme System
5 built-in themes: **Dark** (default), **Light**, **Minimal**, **Tech**, **Brezn**.
Custom themes can be imported as `.breznflow.json` files containing 41 CSS color tokens. Custom themes are stored in `wp_options` and rendered as inline CSS variables.
Themes are selectable globally, per-workflow, or per-shortcode via `theme="dark"`.
---
### Action Bar
Below the diagram (non-compact mode), the action bar provides:
| Action | Control | What it does |
|---|---|---|
| **Share** | Global setting | Shows article link + anchor link for hash navigation |
| **Embed** | Global + per-post | Shows iframe embed code for standalone embedding |
| **Get JSON** | Global setting | Displays formatted JSON with size in KB |
| **Download** | Global + per-post | Downloads sanitized JSON file |
Each action can be toggled globally in settings and overridden per shortcode.
---
### Sensitive Data Masking
BreznFlow never stores raw workflow JSON. Before saving, a two-pass sanitization runs:
**Pass 1 — String sanitization:** All string values pass through `sanitize_text_field()`. Exception: `jsCode` fields are preserved as-is but displayed with `esc_html()` (never executed).
**Pass 2 — Secret detection:**
- **URL parameters:** `api_key`, `token`, `secret`, `password`, `access_token`, `auth`, `client_secret` in query strings → `[REDACTED]`
- **Header values:** Authorization, Bearer, X-API-Key and similar header names in `{name, value}` pairs → value masked
- **High-entropy conditions:** Values in IF/Switch conditions that match UUID patterns, mixed-case+digits, or long strings without spaces → masked via entropy heuristic
A **mask log** records every masked item with the reason, key, and note — shown in the wizard's Step 3 preview.
---
### Display Modes
| Mode | What's shown |
|---|---|
| `visual` | Full diagram with toolbar, detail panel, action bar |
| `info` | Node counts only (InfoBox) — no diagram |
| `compact` | Diagram without toolbar or action bar |
Configurable globally, per-workflow, or per-shortcode.
---
### Embed Handler
Serves a standalone HTML page at `?breznflow_embed={id}` for iframe embedding. The page contains only the SVG renderer — no WordPress theme, no admin bar.
**Dual-gate security:** Both the global `allow_embed` setting and the per-post `_breznflow_show_embed` meta must be enabled.
URL parameters: `?theme={id}` and `?minimap=0|1`.
HTTP headers include `X-Robots-Tag: noindex, nofollow` and remove `X-Frame-Options` to allow embedding.
---
### Additional Features
- **View Counter** — tracks how many times each workflow is displayed
- **Related Workflows** — shows similar workflows by shared node types
- **InfoBox** — compact summary like "3× HTTP Request, 2× Code, 1× OpenAI"
- **AI Detection** — automatically detects and badges workflows containing AI nodes
- **Schema.org HowTo** — optional JSON-LD structured data output
- **Anchor Navigation** — `<span id="breznflow-{id}">` for hash-based deep linking with 60px scroll offset
---
## Data Storage
### WordPress Options (wp_options)
| Option Key | Content |
|---|---|
| `breznflow_settings` | All plugin settings (16 keys, serialized array) |
| `breznflow_custom_themes` | Custom theme definitions (serialized array) |
### Post Meta (wp_postmeta)
| Meta Key | Content |
|---|---|
| `_breznflow_raw_json` | Sanitized workflow JSON (never the raw original) |
| `_breznflow_original_name` | Original workflow name from n8n |
| `_breznflow_node_count` | Total number of nodes |
| `_breznflow_node_summary` | Categorized node counts (JSON) |
| `_breznflow_has_ai_nodes` | Whether workflow contains AI nodes |
| `_breznflow_ai_node_types` | List of AI node types present (JSON) |
| `_breznflow_mask_log` | Masked values during import (JSON) |
| `_breznflow_default_zoom` | Per-workflow zoom level (10200) |
| `_breznflow_show_title` | Show title |
| `_breznflow_show_infobox` | Show info box |
| `_breznflow_show_download` | Allow download |
| `_breznflow_show_embed` | Allow embedding |
| `_breznflow_show_minimap` | Show minimap |
| `_breznflow_default_mode` | Display mode |
| `_breznflow_default_theme` | Theme ID |
### Uninstall Cleanup
`uninstall.php` removes on plugin deletion:
- All `breznflow_workflow` posts and their meta
- Option `breznflow_settings`
- All `breznflow_category` taxonomy terms
- All transients with prefix `breznflow_`
---
## Security
### Input Validation
- Workflow JSON is validated against the n8n schema before import
- All `$_POST` / `$_GET` values processed via `wp_unslash()` + specific sanitizers
- All output escaped with `esc_html`, `esc_attr`, `esc_url`
- SQL queries exclusively via `$wpdb->prepare()`
### CSRF Protection
Every admin action validates a WordPress nonce. Capability checks require `manage_options` for settings and `edit_posts` for workflow management.
### Download & Embed Security
Both endpoints validate:
1. Post exists, is type `breznflow_workflow`, and has status `publish`
2. The corresponding per-post meta permission is enabled
3. The global setting is enabled
4. The stored JSON is valid
Response headers include `X-Content-Type-Options: nosniff`. Downloads use `Cache-Control: no-store`.
### Import from URL
The "Fetch from URL" feature in the wizard blocks requests to private/internal network addresses (localhost, `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, cloud metadata endpoints) to prevent SSRF attacks.
---
## Shortcode
```
[breznflow id="42"]
[breznflow id="42" mode="compact" theme="light" zoom="80"]
[breznflow id="42" show_share="0" show_embed="1" show_minimap="0"]
```
| Attribute | Default | Description |
|---|---|---|
| `id` | — | Workflow post ID (required) |
| `mode` | `visual` | `visual`, `info`, or `compact` |
| `theme` | `dark` | Theme ID |
| `zoom` | `100` | Initial zoom level (10200) |
| `show_title` | `true` | Show workflow title |
| `show_infobox` | `true` | Show node summary box |
| `show_minimap` | `true` | Show minimap overlay |
| `show_download` | `false` | Show download button |
| `show_share` | `true` | Show share action |
| `show_embed` | `false` | Show embed action |
| `show_get_json` | `false` | Show "Get JSON" action |
| `max_code_lines` | `50` | Max lines in code node display |
**Resolution hierarchy:** Shortcode attribute → Post meta → Plugin settings.
---
## Installation
**Via GitHub Release (recommended):**
1. Download `breznflow.zip` from the [latest release](https://github.com/noschmarrn/breznflow/releases/latest)
2. In WordPress go to *Plugins → Add New → Upload Plugin*
**Manual (clone):**
```bash
cd /path/to/wordpress/wp-content/plugins/
git clone https://github.com/noschmarrn/breznflow.git
wp plugin activate breznflow
```
**After activation:**
1. Go to *BreznFlow → Add Workflow*
2. Paste your n8n workflow JSON (or upload a `.json` file)
3. Configure display settings and preview
4. Publish — use `[breznflow id="X"]` in any post or page
The plugin has no build step. All assets are direct JS/CSS files.
---
## Tech Stack
| Component | Technology |
|---|---|
| Backend | PHP 8.0+, WordPress Plugin API |
| Namespace | `BreznFlow\` |
| Architecture | Singleton core, feature classes with `register()` |
| Rendering | Vanilla JavaScript SVG generation (no canvas, no libraries) |
| Database | WordPress Options API + Post Meta |
| Caching | WordPress transients (related workflows) |
| Frontend | Vanilla JS, no build step, no external CDN |
| i18n | `.pot` file, text domain `breznflow` |
| Coding Standard | WordPress PHPCS |
| License | GPL-2.0-or-later |
---
## License
GPL-2.0-or-later — [https://www.gnu.org/licenses/gpl-2.0.html](https://www.gnu.org/licenses/gpl-2.0.html)
Copyright (c) 20252026 [mifupa.com](https://mifupa.com)