=== OA Forms → n8n ===
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 2.3.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Send any number of site forms to their own n8n webhooks, with bot protection added automatically and webhook URLs kept out of the browser.

== Description ==

Point the plugin at a form you already have — by CSS selector or a `data-oa-form` attribute — and it takes over the submission. The browser posts to your own site; PHP verifies the request and forwards it to n8n server-to-server, so the webhook URL and its secret never appear in the page source, in DevTools, or in any cache.

Each form has its own webhook, its own header secret, its own required fields and its own success message.

**Bot protection, added without touching your markup**

* Two honeypot fields
* A signed, single-use token bound to one specific form
* A minimum fill time
* Origin / Referer verification
* Cloudflare Turnstile in `interaction-only` mode — invisible to real visitors
* Rate limiting per IP, counted separately for attempts and successful submissions
* Duplicate suppression
* Server-side validation with an optional field allowlist

**Built to stay out of the way**

Pages without a form get about 300 bytes of inline code and make no extra requests. Pages with a form load one deferred 3.7 KB (gzipped) script. The Turnstile script is fetched only after a visitor interacts with the form, so first paint is untouched. No database tables are created, settings live in a single autoloaded option, and deactivating the plugin returns the site to exactly how it was.

**If n8n is down**

The submission is emailed to you straight away and a single retry is queued three minutes later. The visitor always sees the success message.

== Languages ==

English (default), Russian, Ukrainian, Belarusian. The admin interface follows the language set in your WordPress user profile; if none is set, it follows the site language. Visitor-facing texts are edited separately in the settings and default to English.

== Installation ==

1. Upload the plugin and activate it.
2. Open **Forms → n8n**.
3. Add a form: ID, CSS selector, webhook URL, header secret.
4. In n8n, set the Webhook node to Header Auth with the same secret.
5. Press **Test the webhook** to confirm the connection.

== Frequently Asked Questions ==

= Do I have to change my form markup? =

No. Give the plugin a CSS selector and it adds the honeypot, the token, the status line and the Turnstile widget itself.

= Can I use several forms with different workflows? =

Yes. Add as many as you like; each one gets its own webhook and secret, and they can share a page.

= Where are the secrets stored? =

Encrypted in the database, with a key derived from the salts in `wp-config.php`. A database dump alone cannot reveal them. Constants in `wp-config.php` are also supported and take priority.

= Does my site have to be on Cloudflare to use Turnstile? =

No.

== Changelog ==

= 2.3.0 =
* Security review. The form token is no longer consumed by a failed field validation, so correcting a typo no longer produces "form expired".
* Field validation now runs before the Turnstile call, so a typo costs neither a captcha token nor a round trip to Cloudflare.
* Header secrets are stripped of control characters on save (header-injection hardening).
* The duplicate-suppression fingerprint now includes an anonymised visitor key, so two people sending identical text no longer collapse into one submission.
* Renaming a form no longer loses its stored secret; duplicate form IDs are reported instead of silently dropped.
* A warning is shown when a webhook uses plain http://.
* The page URL sent to n8n is restricted to http/https.

= 2.2.0 =
* Full internationalisation: English source with Russian, Ukrainian and Belarusian translations.

= 2.1.0 =
* All visitor-facing texts moved into the settings screen; English defaults.

= 2.0.0 =
* Multiple forms, each with its own webhook. Admin settings screen. Encrypted secrets. Automatic markup enhancement.
