# Changelog — BW Guides Server

All notable changes to this plugin are documented here.
Format: [Keep a Changelog](https://keepachangelog.com/). This plugin is site
infrastructure (not released via release.sh), but the same conventions apply.

## [0.2.0] - 2026-07-24

### Added
- **Client-group targeting.** Sites carry a `client_slug` (Guides → Sites, new
  "Client" column + inline per-row edit, plus an "Add Site" field). A guide's
  Targeting metabox gains a third audience option, "Specific client", which
  resolves at manifest/guides-fetch time to every *active* site whose client
  matches — including sites registered after the guide was published. DB
  version bumped 1 → 2 (`client_slug VARCHAR(64) NOT NULL DEFAULT ''` +
  index, added additively via the existing dbDelta path — no data loss, no
  deactivate/reactivate needed). `schema_version` (the REST payload contract)
  is unchanged at 1; this is purely a new server-side targeting rule.
- **Search keywords & category authoring.** A new metabox on the guide editor:
  a free-text `Category` field (with a datalist of categories already in use)
  and a `Section keywords` textarea — one rule per line,
  `Heading text :: kw, kw, kw`, with `*` reserved for guide-level keywords not
  tied to any heading. On save, any keyword line whose heading text doesn't
  match a current `<h2>`/`<h3>` in the guide (case-insensitive, trimmed) shows
  a dismissed-on-read admin warning — saving is never blocked. Both are
  forward-compat carriers for the client: exposed as `meta.category` (string)
  and `meta.section_keywords` (array of `{heading, keywords}`) on the
  `/guides` endpoint only. The `/manifest` endpoint, `content_hash`
  computation, and route structure are all unchanged.

### Notes
- Editing `_bw_guides_category` / `_bw_guides_section_keywords` via wp-cli
  directly (rather than through the metabox) does **not** bump
  `post_modified_gmt`, so clients relying on that field to decide whether to
  re-pull a guide won't see the change until something else touches the post.
  Follow a wp-cli meta edit with a no-op `wp_update_post()` touch if the
  client needs to see it.
- The keyword-heading match is a literal string compare (case-insensitive,
  trimmed) against the raw stored heading text — it does not decode HTML
  entities. Type the keyword line's heading using the same characters that
  appear in the block editor (a smart/curly apostrophe typed in the editor is
  not the same string as a plain one in the keyword line).
- The pre-existing Sites-screen "Client" column (showing each site's last
  synced client **plugin** version) is renamed to "Plugin Ver." to make room
  for the new "Client" column (the customer/client-group slug) — same data,
  new label, to avoid two same-named columns meaning different things.

## [0.1.1] - 2026-07-24

### Added
- The BW Guides design kit: seven authoring patterns registered for the
  `bw_guide` post type only — Note callout, Important callout, Numbered steps,
  Do / Don't columns, FAQ accordion, Reference table and Button row. They appear
  in the editor's pattern inserter under a "BW Guides" category.
- Editor stylesheet (`assets/css/editor.css`) loaded on `bw_guide` screens, so
  the hub editor previews the components as client sites will render them.
- Block allowlist for the `bw_guide` editor (24 blocks, via
  `allowed_block_types_all`). Other post types on this site are unaffected.
  Third-party blocks — Kadence above all — can no longer be inserted into a
  guide, which is what let a Kadence pattern reach guide 25 previously.
  Deliberately an allowlist and not "core only", because three *core* blocks
  are also broken in the client's render path, which uses `do_blocks()` alone
  and never the full `the_content` chain:
  `core/embed` (oEmbed filters never run — renders as a bare URL),
  `core/shortcode` (never expanded — prints literal `[shortcode]` text) and
  `core/html` (iframes and scripts stripped by `wp_kses_post`).

### Notes
- Patterns are core blocks only and carry their appearance via plain `className`
  attributes (`bw-callout`, `bw-steps`, …) that the client plugin styles. Two
  reasons: hand-serialized inline style attributes risk Gutenberg's "unexpected
  or invalid content" warning, and class-based components can be restyled in the
  client plugin without editing any published guide.
- Deliberately no theme.json preset colours. WordPress hooks
  `wp_enqueue_global_styles()` to `wp_enqueue_scripts` only, never
  `admin_enqueue_scripts`, and clients read guides in wp-admin — so preset
  palette classes would render colourless there.
- Requires client plugin **0.1.2 or newer** for the component styles. On an
  older client the patterns still render as readable core blocks, just unstyled.

## [0.1.0] - 2026-07-23

### Added
- `bw_guide` CPT for authoring guides in Gutenberg (public=false, show_ui).
- Targeting metabox: audience all-sites vs selected sites, Audience list column.
- Sites registry (`{prefix}bw_guides_sites`): per-site keys generated as
  `bwg_<id>_<40 hex>`, stored sha256-hashed, shown once; regenerate / revoke /
  reactivate / delete row actions; last-sync bookkeeping (time, IP, client version).
- REST API `bw-guides/v1`: public `/health`; key-authenticated `/manifest` and
  `/guides?include=` (max 20 ids, silent omission of non-visible ids).
