0.1.0 - Unreleased

  • Introduces the standalone BlogEngine domain and Elixir API.
  • Adds version-pinned, prefix-aware EctoEvolver migrations generated through the host's Ecto task.
  • Adds non-destructive PostgreSQL schema diagnostics.
  • Adds tenant-scoped authoring, immutable revisions, review, publication, routing, moderation, audit events, tags, and curated syndication.
  • Adds optional host-owned generators for installation, editor LiveViews, public Phoenix pages, and ReqLLM-assisted form suggestions without adding those concerns to the core runtime.
  • Prepares strict Hex package metadata, documentation, and file whitelisting without publishing.
  • ReqLLM 1.20 compatibility for mix blog_engine.gen.ai was verified through Hex dependency resolution plus API-shape stub tests against a 1.20.0-compatible double; a full transitive compile of ReqLLM is currently blocked upstream by abnf_parsec failing on Elixir 1.19 and is therefore not claimed as verified.
  • BREAKING BlogEngine.Notifier callback is now notify(context, event) instead of notify(event), matching Authorizer, RouteRegistry, and Clock. Host notifiers must add the leading BlogEngine.Context parameter. The library no longer injects any actor field into event payloads; a notifier that needs actor or tenant detail reads it from the context.
  • Unifies the lock order across syndication and post-lifecycle commands: blogs (sorted by id), then post, then post revisions, then syndication placements.
  • BlogEngine.Posts.delete_draft/2 now locks and deletes a never-published draft's syndication placements with the post, and fails with :has_syndications when a placement is already approved on a target blog.
  • BlogEngine.Posts.withhold/3 accepts an optional reason, rejects a blank or non-string reason with :invalid_reason, and records the reason in the moderation audit metadata.
  • Editing a post's working revision no longer requires an active author when authorship is not being reassigned, so content stays editable after its original author is deactivated. Reassigning to a deactivated same-tenant author still fails with :author_inactive.
  • Defines an explicit nil policy for author and revision attributes: nil clears a documented clearable field, and is ignored exactly as an omitted key everywhere else, so tag_ids: nil keeps the current tags rather than removing them.
  • Validates :tag_ids as a list of tenant-owned tag UUIDs and fails with :invalid_tag on a malformed, unknown, or foreign-tenant id.
  • Fixes the generated editor form's content echo: set-editor-content is pushed only for authoritative replacements, never on validate, and the hook skips the write when the pushed content already equals the textarea, so a debounced round-trip cannot clobber in-flight typing.
  • Generated editor LiveViews mount gracefully without an authenticated scope instead of crashing, rendering an unauthenticated state for the host to handle.
  • Propagates the real route-template error when a blog-template move compiles a post path, instead of laundering it into an opaque non-binary destination.