=== Cosmobill Connector ===
Contributors: sidular, cosmobill
Tags: invoicing, webhook, cloudflare, ajax, publish
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.3.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Publishes your Cosmobill-linked guest post automatically the moment its invoice is paid. Fixes publish failures on firewalled sites.

== Description ==

Using Cosmobill to sell guest posts or sponsored placements? This plugin makes sure the draft you linked to an invoice actually goes live the moment your client pays — with no extra step from you.

**You probably don't need to install this.** Cosmobill can normally publish to your WordPress site on its own, using a free Application Password you generate in a few clicks. Install this plugin only if that doesn't work for your site — most often because a security firewall (very common on Cloudflare-protected hosting) is quietly blocking the connection, even though everything is set up correctly.

This plugin fixes exactly that, by publishing through a different, firewall-friendly path instead. Once it's installed and connected, everything else works the same: link a draft to an invoice, get paid, and it publishes itself.

**What it does:**

* Flips one already-linked draft post to "Published" the instant its Cosmobill invoice is paid.
* Nothing else. It never edits your content, never touches other posts, and never reads anything about your site beyond that one post's ID.

**What it needs from you:** activate it, create a WordPress Application Password for an existing account that can publish the linked drafts, then copy the webhook URL, shared secret, username, and Application Password into Cosmobill's settings. This plugin never creates or logs in a WordPress user.

== Installation ==

1. In WP admin: **Plugins → Add New → Upload Plugin** → choose the zip → **Install Now → Activate**.
2. Open **Settings → Cosmobill Connector** and copy the webhook URL and shared secret.
3. In **Users → Profile**, create an Application Password for an existing WordPress account with the capabilities needed to publish the linked drafts.
4. In Cosmobill: **Settings → Integrations → WordPress**. Paste the webhook URL, shared secret, WordPress username, and Application Password, then save.
5. Use **Settings → Cosmobill Connector → Test connection** to verify the local setup without publishing a post.
6. The next paid invoice with a linked draft publishes on its own. Repeated delivery for an already-published post is acknowledged safely. Requests that do not pass both HMAC and WordPress Application Password authentication are rejected.

== Frequently Asked Questions ==

= Do I need this plugin? =

Probably not at first — try connecting Cosmobill without it, using a free WordPress Application Password. Only install this plugin if a paid invoice's linked post doesn't go live; that almost always means your site's firewall is blocking the default connection, and this plugin routes around it.

= Does this plugin write or change my post content? =

No. Cosmobill only ever sends a post ID; this plugin changes that one post's status from Draft to Published. Title, content, images, categories — none of it is touched.

= Does it read or send any of my other content? =

No. It doesn't look at, list, or transmit anything about your site's other posts, pages, users, or settings.

= Does it create or log in to a user account? =

No. This plugin never creates users, generates passwords, or implements its own login flow. The site administrator must create an Application Password for an existing WordPress account. The connector passes that credential to WordPress core for authentication, so normal WordPress and security-plugin authentication controls remain in charge.

= What if I think my secret leaked? =

Go to **Settings → Cosmobill Connector → Get a new secret**, then paste the new value into Cosmobill. The old one stops working immediately. Even in the worst case, a leaked secret can only publish/edit existing posts — it can't touch site settings, users, or anything else.

== Screenshots ==

1. The Cosmobill Connector settings page — two values, ready to copy into Cosmobill.

== Changelog ==

= 1.3.0 =
* Fixed Application Password authentication for the admin-ajax webhook path by explicitly enabling WordPress core API authentication for this endpoint.

= 1.2.9 =
* Added a safe capability diagnostic to failed publish responses so administrators can identify the authenticated user and missing WordPress permissions.

= 1.2.8 =
* Fixed a false authorization failure for authenticated Application Password users on some admin-ajax hosting configurations.

= 1.2.7 =
* Version bump only. No functional, security, or copy change from 1.2.0.

= 1.2.0 =
* Added idempotent webhook handling: repeated delivery for an already-published post returns success without changing content.
* Added optional replay protection using `X-Cosmobill-Timestamp` and `X-Cosmobill-Request-Id` headers. Requests must be signed as `<timestamp>.<request-id>.<raw-body>` and expire after five minutes.
* Added an administrator-only configuration check that never publishes or modifies a post.
* Added masked secret display and a last-webhook status indicator in the settings screen.

= 1.1.1 =
* Renamed the plugin to Cosmobill Connector.
* Added the sidular WordPress.org contributor account.

= 1.1.0 =
* Security: removed automatic creation of the `cosmobill-connector` Editor account.
* Webhooks now require a site-admin-configured WordPress Application Password and use WordPress core authentication before checking `edit_post`.
* Added a draft-status guard so the connector only publishes linked draft posts.
* Existing accounts are never deleted by uninstall; administrators should review and remove any legacy service account created by version 1.0.4 or earlier if it is no longer needed.

= 1.0.4 =
* Added the `Author URI` header (https://cosmobill.com/) so WordPress's Plugins list links "By Cosmobill" back to the Cosmobill site instead of rendering it as plain text. No functional change.

= 1.0.3 =
* Rewrote all plugin-facing copy (plugin header, settings screen, this readme) to be plain-language and consumer-friendly, aimed at a non-technical blog owner rather than a developer. No functional or security change.
* Settings screen: removed a stale "Click Generate shared secret" instruction — the secret has always been generated automatically on activation, there was never a button for it.
* Moved the curl test snippet and signing details behind an optional "Advanced" disclosure on the settings screen so they don't have to be read by everyone.
* Renamed the "Rotate secret" button to "Get a new secret" with a plainer explanation of when (and why) to use it.

= 1.0.2 =
* Bumped "Tested up to" to 7.0 (current WordPress release) so the plugin shows up correctly in WordPress.org search results.
* Trimmed `Tags:` to 5 (WordPress.org limit) and removed the self-branded `cosmobill` tag per directory guidelines.
* Added an inline `phpcs:ignore` justification for the `rotated` GET flag read on the settings page: it is a read-only, post-redirect success flag with no side effects, and the actual state-changing action (secret rotation) already requires `manage_options` and a verified nonce in `cosmobill_connector_handle_rotate()`. No functional/security behavior change.

= 1.0.1 =
* Packaging fix: the distributed zip now wraps the plugin files in a `cosmobill-auto-publish/` folder matching the plugin slug, so WordPress correctly recognizes a re-upload as an upgrade of the installed plugin instead of installing a duplicate copy. No functional/code change.

= 1.0.0 =
* Initial release. Publishes linked Cosmobill invoice drafts via signed `admin-ajax.php` webhook, with shared-secret rotation and a local `cosmobill-connector` editor user.

== Upgrade Notice ==

= 1.3.0 =
Fixes authenticated admin accounts being reported as user ID 0 and rejected from publishing through the connector.

= 1.2.9 =
Adds diagnostic details to authorization failures so WordPress permissions can be fixed without guessing.

= 1.2.8 =
Fixes a false authorization failure that could prevent a correctly authenticated administrator from publishing a linked draft.

= 1.2.7 =
Version bump only. No functional or security change. Safe to update.

= 1.2.0 =
Adds safer retries, optional replay protection, a configuration check, and clearer webhook status reporting. No migration is required.

= 1.1.1 =
Renames the plugin to Cosmobill Connector and includes the latest security update. Configure a WordPress Application Password for publishing.

= 1.0.4 =
Adds an Author URI link only. No functional or security change. Safe to update.

= 1.0.3 =
Copy/wording improvements only — friendlier settings screen and readme. No functional or security change. Safe to update.

= 1.0.2 =
Compliance fixes only (Tested up to 7.0, tag limit, documented nonce exemption). No functional change. Safe to update.

= 1.0.1 =
Packaging fix only - re-zips with the correct wrapper folder so future updates install over the existing plugin instead of creating a duplicate. Safe to update.

= 1.0.0 =
First public release.

== Security Model ==

* Shared secret = 32 bytes from `random_bytes`, hex-encoded (64 chars), generated automatically on activation.
* Verified with `hash_equals` (constant-time).
* Optional `sha256=` prefix is stripped on the server so the client can send either `sha256=<hex>` (matching GitHub-style webhooks) or just `<hex>`.
* The webhook requires both the shared HMAC secret and a WordPress Application Password.
* Application Password validation is delegated to WordPress core; the plugin does not create users, generate passwords, or implement a custom login flow.
* The authenticated account must pass `current_user_can( 'edit_post', $post_id )`. Drafts are published; already-published posts are acknowledged without modification; other statuses are rejected.
* Legacy body-only signatures remain supported. For replay protection, send `X-Cosmobill-Timestamp` and `X-Cosmobill-Request-Id`; sign `<timestamp>.<request-id>.<raw-body>` with the shared secret. Timestamps outside a five-minute window and duplicate request IDs are rejected.
* Get a new secret any time from Settings -> Cosmobill Connector. Old secret stops working immediately.

== Uninstall ==

Click "Delete" on the Plugins page (not just "Deactivate"). The uninstall hook removes the connector's shared-secret option only. It never deletes WordPress users, including any legacy service account created by an earlier version.
