=== Final Copy Publisher ===
Contributors: finalcopy
Tags: rest-api, publishing, headless, drafts, markdown
Requires at least: 6.5
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Receives article pushes from the Final Copy editorial portal and creates WordPress drafts — reliably, even behind Cloudflare and Authorization-stripping origins.

== Description ==

Final Copy Publisher is the WordPress side of the Final Copy newsroom pipeline. It exposes a single, token-authenticated REST endpoint that the Final Copy portal calls to create or update **draft** posts.

It exists because the standard WordPress REST route (`/wp-json/wp/v2/posts`) is unreliable for automated server-to-server publishing in the real world:

* Cloudflare Super Bot Fight Mode challenges automated `POST`s to `/wp-json/*`.
* Many origins strip the HTTP `Authorization` header before PHP sees it, so Application Passwords return `rest_not_logged_in`.
* The REST API expects pre-rendered HTML and numeric term/author IDs that a headless editor rarely has.

This plugin solves all of that:

* **Custom-header token auth** (`X-FinalCopy-Token`, with a request-body fallback) — never the `Authorization` header, so nothing gets stripped.
* **Markdown rendered server-side** (bundled Parsedown) and sanitized with `wp_kses_post()` — no more raw `**bold**`.
* **Categories, tags and author resolved by name** (create-if-missing is opt-in).
* **Images sideloaded by WordPress itself** from their public URL, with SSRF hardening — the portal never uploads bytes.
* **Idempotent**: every article carries its source UUID, so retries update the same post instead of creating duplicates.
* **Always a draft.** The plugin never auto-publishes; a human clicks Publish in WordPress.

== Installation ==

1. Upload the `final-copy-publisher` folder to `/wp-content/plugins/` (or upload the ZIP via Plugins → Add New → Upload).
2. Activate the plugin.
3. Set Settings → Permalinks to any non-Plain option (e.g. Post name) so the pretty /wp-json/ route resolves and the Cloudflare path rule matches.
4. Go to **Settings → Final Copy Publisher**.
5. Copy the **Publish endpoint** and **Shared secret** into your Final Copy portal environment as `FC_PLUGIN_URL` and `FC_PLUGIN_TOKEN`.
6. Set a **Default author** (recommended) and a **Default category** (optional).
7. If the site is behind Cloudflare, add the WAF Skip rule described in the bundled README.md.

== Frequently Asked Questions ==

= Does it ever publish posts live? =

No. It only ever creates drafts (or, via a filter, pending review). Publishing stays a human action.

= Where is the token stored? =

In an autoloaded-off WordPress option, or — more securely — in a `FCPUB_SHARED_SECRET` constant in `wp-config.php`, which always wins over the option.

= Will re-pushing the same article create duplicates? =

No. Each push includes the article's external UUID; the plugin updates the existing post if it has seen that UUID before.

== Changelog ==

= 1.0.2 =
* Fix: the v1.0.1 CSP fix was never shipped in the distributed zip — the download still contained v1.0.0, whose inline script is blocked by a strict Content-Security-Policy, so Reveal/Copy did nothing. Rebuilt so the enqueued asset actually ships.
* The token is now revealed by a native `<details>` element and shown in full in a selectable field, so you can show + manually copy it with no JavaScript at all (works under any CSP). The Copy button and select-all-on-focus remain as enhancements.

= 1.0.1 =
* Fix: settings-screen Reveal/Copy buttons did nothing under a strict Content-Security-Policy. Moved the inline script + inline event handlers into a properly enqueued asset. Added Copy buttons for the endpoint and token (the token copies even while masked) and a CSP-safe regenerate confirm.

= 1.0.0 =
* Initial release: token-authenticated `finalcopy/v1` REST namespace (publish/health/status/taxonomies), server-side markdown rendering, by-name taxonomy/author resolution, SSRF-hardened image sideloading, idempotent create-or-update, admin settings + push log.
