=== WeBlog Connector ===
Contributors: lazyingart
Tags: weblog, rest-api, application-passwords, publishing
Requires at least: 6.2
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 0.1.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Required, reusable authenticated WordPress connection and publishing for WeBlog. Each WeBlog account connects its own site with its own WordPress credentials; no personal blog or shared credentials are supplied by the app.

== Installation ==

1. Obtain weblog-connector-0.1.0.zip from your WeBlog operator. It must contain the weblog-connector directory and this readme. No hosted public download is claimed by this source release.
2. In the target WordPress site's dashboard, choose Plugins > Add New > Upload Plugin. Select the ZIP, install, and activate. Alternatively copy weblog-connector into that site's wp-content/plugins directory and activate it there.
3. Use HTTPS with a valid certificate. WordPress must correctly detect HTTPS when behind a trusted reverse proxy. Do not disable the HTTPS check to bypass a proxy setup problem.
4. Create or select a dedicated WordPress author/editor with permission to edit posts. Publishing or private status also requires publish_posts. The plugin never grants capabilities or edits WordPress roles.
5. In Users > Profile > Application Passwords, create an application password named WeBlog. Keep it private; revoke it from the same page to disconnect permanently.
6. Sign in to your independently configured WeBlog server. Add the exact HTTPS site base URL (including a subdirectory if present), WordPress username, and application password under Blog connections. Do not enter the main WordPress login password.
7. WeBlog checks credentials, edit_posts permission, and the authenticated connector status before saving the encrypted connection. Version 0.1.0 already supplies the required status fields. WeBlog rechecks this permission and connector before remote reads and writes; WordPress post-specific permissions remain authoritative. Review the generated draft, choose categories and target status, then explicitly publish. Chat and autosave never publish automatically.

Invitations grant access to a WeBlog account, not to the inviting person's blog, posts, conversations or credentials. Even a WeBlog owner account has no automatic access to another account's connections. A WordPress editor may access posts allowed by that site's WordPress roles; the connector does not expand those roles.

Older core-only connections remain saved for history but cannot read or publish through WeBlog until verified with the connector. Install and activate it on the same site, then reconnect that existing connection using your own application password. Reconnection preserves the connection ID, site URL, posts and receipts. Resolve any uncertain publish by exact read-only reconciliation before reconnecting; do not delete the connection or create another post to bypass an unresolved write. There is no core REST publishing fallback.

== Interface ==

All routes live under /wp-json/weblog/v1. WordPress REST authentication uses Application Passwords or WordPress's normal nonce-protected authenticated REST session. Every route requires HTTPS and edit_posts.

* GET /status returns connector name, version and idempotency capability.
* POST /posts accepts idempotency_key, optional post_id, title, HTML content, draft/publish/private status, and the exact array of existing integer category IDs. Empty categories explicitly clears assignments.
* GET /operations/{key} returns the original receipt for the current authenticated WordPress user only. Current edit_post permission is checked before returning a successful receipt.

Creation always belongs to the authenticated WordPress author. Updates require the exact existing post ID and edit_post capability. No URL downloads, executable user code, shell execution, theme edits, core patches, or changes to another WordPress installation are performed. Standard WordPress hooks still execute normally for explicit writes.

== Retry and recovery ==

Use the same stable idempotency key for the same exact payload. Replays return the first receipt. Changed payloads conflict. A durable pending record survives disconnects and process death and is never stolen or blindly recreated. If a crash occurs between the WordPress write and saving its receipt, the operation remains uncertain (HTTP 409); the operator must inspect the exact site/post before reconciliation. Do not generate another key to bypass an uncertain creation.

The plugin creates only the current site's prefixed weblog_operations table on activation. There is no uninstall hook that deletes posts or receipts. Deactivation leaves posts and the journal intact. The journal stores operation hashes, WordPress user/post IDs, statuses and receipt URLs, not application passwords or article bodies. Retain it for idempotency; back it up with the site database.

== Packaging from source ==

From the WeBlog repository, run wordpress/package.py --output /an/external/artifact/path. This builds a reusable ZIP without credentials or runtime state. No public distribution/upload is performed by the packaging command.

== Privacy ==

The connector itself contacts no external service. The WeBlog server receives the selected site's credentials and explicitly requested post data, and sends chat/draft text to the operator-configured AI provider. Confirm the provider disclosure in the native app before sending. Disconnecting or deleting a WeBlog account does not delete remote WordPress posts.

== Changelog ==

= 0.1.0 =
Namespaced, permission-checked explicit post create/update, exact categories, content sanitation, durable per-user idempotency journal, and receipt lookup.
