Release history

DivisionDesk Changelog

Every package carries a cumulative changelog. The Server keeps release history even when an old package file is removed.

DivisionDesk Server

DivisionDesk Server release history
# DivisionDesk Server 1.22.10 — Licensing, Commerce & Unified Support

## Licensing and installations
- Extended the existing customer/license/entitlement/activation architecture rather than creating a parallel licensing system.
- Added cryptographic installations with Production, Staging, Development, Demo, and Review classes; normalized domains and controlled wildcard domain families; Server-signed installation certificates; refresh and controlled transfer; and Active/Grace/Expired/Suspended/Revoked lifecycle behavior.
- Added monthly, yearly, and perpetual entitlement terms, administrator-controlled offered terms, per-entitlement expiration/renewal/grace, complimentary/manual licensing administration, customer contacts, manual billing records, and renewal metadata.
- Preserved legacy client activations and explicit enrollment semantics so a Core upgrade alone does not enroll or enforce an existing installation.

## Commerce / Cubicle
- Added Server-authoritative product visibility for public catalog, customer/client, organization type, assigned license, and hidden/admin-only rules.
- Added provider-neutral checkout/order/license issuance using existing Server module payment capabilities; browsers cannot self-assert successful payment and raw card data is not stored.
- Added coupon restrictions, multi-period introductory promotions, reseller-ready customer discount/commission separation, and itemized recurring renewal processing.
- Added scheduled renewal notices (10-day default) and renewal charges through vaulted-payment capabilities plus a single Server mail-delivery service.

## Support and telemetry
- Unified telemetry and support cases around case history/status lifecycle, including regression reopening, notes/replies, customer visibility, and signed Core Report-a-Problem intake.

## Compatibility and QA
- Hardened MySQL/SQLite portability in licensing and related live Server upsert paths.
- Added licensing/commercial regression checks and documented new public licensing/support/checkout APIs.

# DivisionDesk Server 1.22.9

## Error telemetry ingestion corrective release

- Fixed the public error-report receiver so accepted Core telemetry is inserted into the canonical `error_reports` database table consumed by Administration → Errors and Support.
- Preserved the daily JSONL stream as a secondary diagnostic archive rather than the canonical telemetry store.
- The receiver now retains `client_key`, generates a fingerprint when omitted, maps Core payload fields to the existing Server schema, and returns HTTP 500 instead of a false success when database persistence fails.
- No Core telemetry contract change is required.

# DivisionDesk Server 1.22.8

## Social inbox identity and reply contract

- Social OAuth Contract v1 action endpoint now supports `reply_comment` and `reply_message` in addition to publish/inbox.
- Facebook comment/message inbox normalization requests explicit sender id/name fields and returns reply metadata to the client.
- Instagram comment rows return reply metadata for inline replies.
- Facebook Page message replies use the connected Page credential retained on DivisionDesk Server; Meta access tokens remain Server-side.
- No Store/package delivery contract changes.

# DivisionDesk Server 1.22.7

## Store release delivery integrity release

- Added deterministic Store release resolution for download authorization and compatibility delivery.
- If duplicate historical release rows exist, Server evaluates candidates and selects the published row whose stored SHA-256 matches the actual immutable release file.
- A checksum failure now reports package type, slug, version, stored SHA-256 and actual file SHA-256 instead of a generic HTTP 409.
- Published `type + slug + version` archives are immutable. Publishing different bytes under an existing version is rejected; publishers must increment the version.
- Server version is now visible in the shared Administration header.
- Retains Store trust propagation, Meta v25.0 and Social OAuth execution bridge from 1.22.6.

# DivisionDesk Server 1.22.6

## Production package-staging corrective release

- Package PHP syntax validation now forces parser diagnostics to stdout (`display_errors=1`, `log_errors=0`) so staging reports the actual parse error and line instead of only `Errors parsing ...`.
- Retains the Store trust propagation, Meta v25.0, OAuth, MySQL migration and release-management fixes from 1.22.5.
- Coordinated with DivisionDesk Core 4.3.8 and Social Media 1.0.11.

# DivisionDesk Server 1.22.5

## Coordinated production release

- Assigns a unique production version to the finalized Store trust propagation and Meta execution work developed during 1.22.4 QA.
- Canonical and legacy/fallback Store catalog paths both expose Server-authoritative package trust, security review state and reviewed permission grants.
- Semantic package version selection and permission-expansion review reset remain enabled.
- Meta Graph API default remains v25.0; existing Social OAuth Contract v1 URLs remain unchanged.
- Intended coordinated baseline: DivisionDesk Core 4.3.7 and Social Media 1.0.11.

# DivisionDesk Server 1.22.4

## Store trust + Meta standards corrective release

- Store schema 4 catalog now emits authoritative top-level `server_trust`, `security_review_state`, `official`, and `granted_permissions` in addition to nested trust metadata.
- Only packages marked **Official** by DivisionDesk Server **and** whose security review is `passed` receive the exact permissions declared by that reviewed manifest.
- Community/Trusted packages receive no implicit third-party network grant.
- Store catalog selects the newest published release using semantic version comparison instead of lexical/text comparison.
- Publishing a module release that expands its declared permission set automatically resets the package security review to `unreviewed`; the widened release must be reviewed before it gains Official privileged execution.
- Meta Graph API default updated to v25.0 for the 2026 release line.
- Existing Social OAuth Contract v1 callback/start/status/assets/select/disconnect endpoints remain unchanged; `/api/social/oauth/v1/action.php` remains the authenticated execution bridge.

# DivisionDesk Server 1.22.3

## Social Media execution bridge

- Added the authenticated `/api/social/oauth/v1/action.php` endpoint so client modules can publish and retrieve supported inbox activity through a selected Server-held Meta connection without exposing provider access tokens to client installations.
- Facebook Page publishing supports text/feed and image/photo posts. Instagram Professional publishing supports image URL container creation and publish.
- Facebook comments/Page conversations and Instagram comments can be synchronized when the app has the required permissions; unavailable Page messaging is returned as a warning rather than corrupting the connection.
- Existing Social OAuth Contract v1 start/status/callback/assets/select/disconnect URLs are unchanged.
- Packages administration now chooses latest releases with semantic version comparison and consolidates duplicate legacy type+slug identity records in the package list instead of showing indistinguishable cards.

# DivisionDesk Server 1.22.2

## Database migration corrective release

- Fixed SQLite → MySQL/MariaDB migration failures caused by legacy invalid UTF-8/binary byte sequences stored in text columns such as `knowledge_training_items.extracted_text`.
- Cross-engine copy now validates text values for UTF-8, repairs invalid sequences deterministically with Unicode replacement characters (or safe byte removal when mbstring is unavailable), and leaves true BLOB/BINARY columns untouched.
- Migration reports now record repaired text counts by table/column so data cleanup is visible rather than silent.
- Content verification hashes normalize the source with the same text-repair rules used for the destination, so repaired text can still be verified deterministically.
- A failed migration now attempts to remove only the destination tables created by that migration, because preflight requires an empty destination before any copy begins.
- Added **Clean Failed Destination** recovery from Administration → Database. Cleanup is allowed only when the supplied destination exactly matches the latest failed/cancelled migration report.
- No Social OAuth Contract v1 endpoint changed.

# DivisionDesk Server 1.22.1

## Corrective release

- Fixed recurring HTTP 419 `csrf_failed` responses caused by the shared CSRF validator always preferring `X-CSRF-Token` over a valid form token for the requested scope.
- CSRF validation now accepts any supplied token that correctly matches the requested scope; an invalid/stale header cannot override a correct form token.
- The unauthenticated administrator login page no longer receives authenticated-admin CSRF metadata, fetch-form interception, admin application JavaScript, or push JavaScript.
- Added a regression check proving a stale admin header plus a valid login form token succeeds, while invalid tokens remain rejected.
- No public API endpoint URL or Social OAuth Contract v1 URL changed.

# DivisionDesk Server 1.22.0

## Public-release stabilization

- Restored and hardened guided SQLite ↔ MySQL/MariaDB migration with preflight checks, atomic maintenance locking, deterministic batched copying, ID preservation, row/content verification, index/foreign-key reconstruction, rollback protection, cancellation, and safe configuration switching.
- MySQL/MariaDB is the recommended production Server database; SQLite remains supported for light/development use.
- Promoted Server Modules to a first-class administration workspace with install/update/reinstall/enable/disable/uninstall, settings, Help, scheduler jobs, scoped permissions, runtime validation, encrypted sensitive settings, rollback protection, and direct module administration pages.
- Hardened Server-module package validation: PHP syntax, callable `server/module.php`, `server_permissions`, ZIP traversal/symlink checks, global-state isolation, duplicate registry protection, and Server-runtime package verification.
- Added/expanded the public Community and verified Feature Requests areas with searchable/indexable discussions, request status, voting, moderation, reporting, structured metadata, and permanent detail URLs.
- Expanded the outward-facing website, public search, sitemap, FAQ, Developers area, Help discovery, product content, and Store package-type coverage.
- Added substantive DivisionDesk Privacy Policy and Terms of Use documents with permanent `/privacy.php` and `/terms.php` routes backed by versioned Legal & Policies records.
- Expanded Help and developer documentation, including the Server API Reference, Server Module SDK, Developer Documentation Index, Community/Feature Request guidance, and current public Help topics.
- Standardized Server administration on the shared Admin UI/navigation/search shell and expanded loading/busy/error feedback for fetch/AJAX actions.
- Hardened Knowledge Trainer document ingestion, URL/crawler SSRF protection, redirect validation, supported file filtering, review/flush operations, and MySQL portability.
- Hardened licensing, entitlement, compatibility, trial, expiration/grace, package download authorization, and package-management validation.
- Expanded HTTP-method enforcement, CSRF/session protections, setup reinitialization protection, security headers, scheduler overlap/schedule validation, and transient-data cleanup.
- Expanded Server Health into the public-release readiness dashboard; individual Store-module compatibility review is informational rather than a Server 1.22 release blocker.
- Social OAuth Contract v1 endpoint URLs remain unchanged.

# DivisionDesk Server 1.21.4

- Fixed Social OAuth endpoint class resolution. PHP `use` imports are file-scoped; importing `Platform\Core\SocialOAuth` inside `_bootstrap.php` did not make the short name `SocialOAuth` available in files that required that bootstrap.
- Every public Social OAuth / Meta endpoint now calls `\Platform\Core\SocialOAuth` explicitly.
- This fixes `DivisionDesk Server returned HTTP 400: Class "SocialOAuth" not found`.
- Applies to OAuth start/status/assets/select/status/disconnect/callback plus Meta webhook, deauthorization and data-deletion handlers.
- No Social OAuth Contract v1 URL or request/response schema changed.

# DivisionDesk Server 1.21.3

- Corrected `public/api/social/_bootstrap.php` so it loads `public/_store_bootstrap.php` instead of the account-home `_store_bootstrap.php`.
- Meta data-deletion and deauthorization URLs now return clean JSON 405 responses to browser GET requests before bootstrapping.
- Replaced malformed inline Social OAuth Copy button JavaScript with safe event listeners and clipboard fallback.
- Added explicit dual-runtime `server_permissions` support while preserving legacy simple-array Server permissions.
- Social OAuth Contract v1 endpoint URLs and required schemas are unchanged.

# DivisionDesk Server 1.21.2

- Fixed Stage Package action dispatch.
- Store Inbox root ZIP discovery and auto-detection.
- Fixed responsive sidebar ID preservation.
- Social OAuth Contract v1 unchanged.

# DivisionDesk Server 1.21.1

## Corrective release
- Fixed Stage Package JavaScript parse failure caused by duplicate `stageButton` declaration.
- Isolated Upload & Validate initialization in its own scope with unique identifiers.
- Upload & Validate now shows `Uploading & Validating…`, disables during the request, and restores controls on completion.
- Added responsive admin navigation drawer at widths 900px and below.
- Narrow screens now overlay navigation instead of squeezing content and causing horizontal scrolling.
- Added backdrop, Escape-to-close, automatic close after navigation, and desktop resize reset.
- Social OAuth Contract v1 is unchanged.

# DivisionDesk Server 1.21.0

# DivisionDesk Server 1.21.0

## Social OAuth Broker
Adds the frozen Social OAuth Broker Contract v1 for official DivisionDesk Social Media integrations. Meta/Facebook is the first provider. App secrets and provider tokens remain on DivisionDesk Server; clients receive only short-lived OAuth session credentials and opaque connection credentials.

Permanent Meta callback paths:
- `/api/social/oauth/v1/callback.php`
- `/api/social/deauthorize/meta.php`
- `/api/social/data-deletion/meta.php`
- `/api/social/webhooks/meta.php`

Server Administration → Social API & OAuth configures the Meta App ID, encrypted App Secret, Facebook Login for Business Configuration ID, exact callback URLs and webhook verify token.

## Administration
- All legacy admin pages are normalized to the same `AdminUi` sidebar at render time.
- Sidebar navigation now includes live filtering/search.
- Core Releases and Store Inbox are merged into **Publisher & Store Inbox**.
- Stage Package type is always auto-detected and hidden.
- Upload & Validate opens a hidden ZIP picker and submits immediately after file selection.

## Knowledge Trainer
- Document-only training targets PDF, DOC/DOCX, RTF, ODT, XLS/XLSX, CSV, TXT/MD and PPT/PPTX.
- CSS, JavaScript, fonts, images, media and archives other than training ZIPs are not trained.
- Spider HTML pages are traversal-only and are not retained as knowledge items.
- Added **Flush rejected** and **Flush everything not approved** actions.

## Contract discipline
Social OAuth routes are versioned and frozen. Breaking changes require Contract v2 rather than renaming or changing required v1 fields.



## 1.20.0 — Unified Packages administration

- Consolidates Store catalog, package discovery and routine publishing management around a single Packages workspace.
- Adds conditional package quick actions such as Approve and Make Official only when they are applicable.
- Simplifies Package Management with status-first summaries and progressive disclosure for advanced lifecycle/security details.
- Adds Server-authoritative runtime overrides (Client / Server / Both) while preserving the package-declared runtime separately.
- Keeps Server installation validation separate: assigning Server/Both does not bypass server/module.php or security validation.
- Adds visible fetch/AJAX busy overlay and operation-specific labels while disabling controls to prevent duplicate submissions.
- Carries forward the PHP Store download compatibility endpoint used to avoid static ZIP HTTP 403 failures.
- Includes the corrected connected-modules.svg XML and a standards-compliant llms.txt with an H1 and public links.
# DivisionDesk Server Changelog

## 1.19.2
- Replaced Store catalog static ZIP download URLs with the PHP compatibility delivery endpoint to bypass hosting-level `/releases/*.zip` 403 rules.
- Added Core-version detection from `DivisionDesk-Core/<version>`, `X-DD-Core-Version`, or `core_version`, with min/max Core enforcement at download time.
- Added transitional client/license validation using registered client identity plus active platform license/grace state, organization applicability, and package entitlement when credentials are supplied.
- Restricted legacy unauthenticated downloads to Free/Included packages so paid/restricted packages cannot bypass entitlement checks.
- Added a Server configuration kill switch for legacy package downloads while preserving the signed short-lived-token flow as the permanent architecture.
- Converted public storefront assets/home illustrations to canonical DivisionDesk asset URLs and added a graceful fallback for broken featured Store artwork.
- Updated Store Help and release QA documentation.

## 1.19.1 - Store download compatibility endpoint

- Replaced transition catalog links to static `/releases/.../*.zip` files with a Server PHP compatibility download endpoint.
- The compatibility endpoint verifies package/version publication state, lifecycle/security state, archive containment and SHA-256 before streaming the ZIP.
- This avoids shared-host/Apache security rules that return HTTP 403 for static ZIP paths while preserving the existing Core Store download contract.
- Repository generation and legacy addon/theme publishing helpers now emit the compatibility endpoint URL.
- Signed entitlement/token download endpoints remain available for coordinated future enforcement.

# DivisionDesk Server 1.19.0

- Added a Server-side Module runtime aligned with the DivisionDesk Integration SDK direction.
- Module packages can declare client, server, or both runtimes; legacy modules remain client-only.
- Added Server Modules administration for approved Store modules, runtime health, enable/disable, update/reinstall, and uninstall.
- Added module-scoped admin/public pages, scheduler jobs, events, capabilities, settings, Help, migrations, and permission-gated database access.
- Added Server-controlled runtime trust/review/install approval fields and Store API runtime metadata.
- Server-compatible module inspection rejects prohibited global application state and requires `server/module.php`.
- Incorporated the post-1.18 project direction: newer modules integrate through the SDK, while merchant payment-fee logic remains in the Payments SDK rather than being duplicated in Storefront or Server.

# DivisionDesk Server 1.18.2

- Fixed Core updater/installer HTTP 403 by exempting `/releases/core/` archives from Store package archive blocking.
- Kept non-Core Store archives behind entitlement/token authorization.
- Restored strict HTTP post-publish verification for Core ZIPs.

# DivisionDesk Server Changelog

## 1.18.0 — Conversation Messenger
### Added
- Persistent threaded public visitor conversations across page navigation.
- Dedicated Server Administration → Messages interface with direct replies, preset replies, conversation status and administrator presence.
- Configurable scheduler-driven unanswered-message automatic replies.
- Explicit visitor Leave conversation state.
- Push notifications now use the visitor name when available, include the actual incoming message, and deep-link to the exact conversation.

### Changed
- Public Messenger is now a conversation window rather than a one-shot contact form.
- The older Support website-message table is retained only for legacy messages and links administrators to the new Messages interface.

## 1.13.0 — Knowledge Service
### Added
- Versioned document knowledge service with registered-client validation.
- `knowledge-analyze`, `knowledge-feedback`, and `knowledge-types` API endpoints.
- Curated document-type and recognition-signal registry with public-source provenance.
- Structural learning from confirmed field labels and remembered layout hashes.
- Internal knowledge review console and product-opportunity backlog for future module ideas.
- Initial cross-module action recommendations for Documents, Finance, Rosters, Communications, and Events.

### Privacy / Reliability
- Raw submitted document text is analyzed ephemerally and is not stored in the knowledge database.
- Retained analysis data is limited to fingerprints, structural feature tokens, field labels, predictions, and feedback.
- Analysis requires a registered DivisionDesk client key.

## 1.12.0 — 2026-08-15
### Fetch-first Administration
- Added Server-wide fetch handling for normal POST forms.
- Publisher uploads/publishing, package management, settings, account actions, requests, announcements, support tools and other Server Administration forms no longer navigate the browser with POST.
- Existing page-specific fetch handlers keep control of forms they already manage.
- Multipart file uploads and attachment downloads are supported.
- The Server setup page and packaged browser installer also use fetch-first submissions.
- The bundled demo site receives the same Core fetch-form behavior.
- A release audit confirmed every browser-facing POST form in Core/Server is on a fetch/AJAX path; API endpoints and CSRF helpers are not browser forms.

## 1.11.5 — 2026-08-15
### Fixed
- Release Publisher now auto-detects Core/Module/Theme/Widget/Site Template/Page Layout from the ZIP's required root files.
- Manual package-type selection is cross-checked against ZIP contents before the package-specific validator runs.
- A Module can no longer be accidentally sent through Core validation because the Publisher form defaulted to Core.
- Store Inbox no longer considers a same-checksum stage from a different package type to be the same staged package.

### Changed
- Release Publisher defaults to **Auto-detect from ZIP (recommended)** rather than Core.
- Package-type mismatch errors identify both the detected type and the incorrectly selected type.

## 1.11.4 — 2026-08-15
### Added
- Bounded DNS TXT resolver support.
- Independent RSA-SHA256 DKIM verification using the actual received RFC message and DNS public key.
- DMARC evaluation can now pass through independently verified aligned DKIM when the receiving mailbox does not add Authentication-Results.
- DMARC output explains policy-only vs actual pass/fail evidence.

## 1.11.3 — 2026-08-14
### Improved
- Live mail-test rate limit is now configurable from Server → Mail Testing.
- Default limit increased from 12 to 30 tests per registered installation per rolling hour.
- Rate-limit errors now report current usage, configured limit, and approximate time until the oldest test leaves the window.
- Server owner can use a fetch-driven **Reset Test Rate Limit** action during troubleshooting/development.
- Mail Testing page displays current rolling-hour test usage.

### Safety
- Resetting the limiter does not delete completed test reports. Completed/failed/expired test timestamps are moved outside the active limiter window so audit/results remain available.
- Active waiting/received tests are not reset.

## 1.11.2 — 2026-08-14
### Fixed
- Live deliverability analysis no longer depends on unbounded `dns_get_record()` calls for DNSBL/domain reputation checks.
- Added `FastDns`, a bounded UDP DNS A-query client with a 1.25-second per-resolver timeout.
- Slow, blocked or unavailable DNSBL providers now become **Unable to Check** instead of holding the entire Server API request open.
- Live reputation analysis caps the number of sending IPs/domains checked per message to prevent templates with many links from creating runaway synchronous DNS work.
- Analysis results now include execution time for diagnostics.

### Performance
- The live status request remains synchronous on shared hosting, but reputation I/O is now explicitly bounded so the Communications modal can receive a response instead of timing out at the client.

## 1.11.1 — 2026-08-14
### Fixed
- Reputation/DNSBL checks are now provider-aware instead of treating every DNS A response as a blocklist hit.
- Spamhaus `127.255.255.*` resolver/error responses are reported as **Unable to Check**, never as listings.
- Spamhaus DBL `127.0.1.255` is recognized as an invalid IP-style query response rather than a domain listing.
- Spamhaus ZEN return codes are classified into SBL/CSS/XBL/DROP/PBL evidence.
- SURBL `127.0.0.1` is recognized as blocked access rather than a listing.
- Unexpected non-loopback DNSBL responses are treated as resolver/interception problems instead of listings.
- Maildir test messages are now deleted after analysis, and the database deletion timestamp is recorded only after the mailbox file is actually removed.
- Already-completed/failed/expired DivisionDesk test messages left in Maildir are recognized as stale test copies and removed without re-analysis.

### Improved
- Reputation results retain the exact provider, tested IP/domain, DNS query, returned addresses and interpretation.
- Authentication analysis checks Authentication-Results, ARC/X authentication results, Received-SPF, SpamAssassin rule evidence, DKIM-Signature presence and DMARC DNS-policy presence.
- DKIM signature presence and DMARC policy presence are no longer mislabeled as successful validation.
- Inbox Probability is coverage-aware: unavailable SpamAssassin, unconfigured reputation providers and unknown authentication signals do not lower the score.
- Reports now include a separate `test_coverage` percentage showing how much evidence was actually measured.

## 1.11.0 — 2026-08-14
### Added
- SpamAssassin engine chain: local `spamassassin`, local `spamc`, or authenticated remote DivisionDesk Spam Worker.
- Standalone DivisionDesk Spam Worker package for deployment on a server where SpamAssassin and daily rule updates can be controlled.
- Shared-hosting-aware Mail Testing administration for remote worker configuration.
- Maildir diagnostics showing root/new/cur readability and message-file count.

### Fixed
- Live mailbox polling now uses one shared Maildir scanner for manual and targeted checks.
- Targeted polling tolerates folded headers and validates the exact DivisionDesk test ID.
- Manual Poll Mailbox now reports how many messages were examined and processed instead of returning an uninformative failure.
- Mail-test status returns mailbox warnings to the client.

### Changed
- Shared hosting no longer needs local SpamAssassin for live analysis; the public Server can delegate only the transient raw message to a signed remote worker.
- Raw messages remain transient and are removed after analysis.

## 1.10.1 — 2026-08-14
### Fixed
- Live Deliverability tests no longer wait for the cron worker after the message has already arrived.
- The test-status API performs a targeted mailbox lookup while a test is still waiting or received.
- Maildir lookup searches newest mail first for the exact `X-DivisionDesk-Mail-Test-ID`.
- Targeted live polling ignores older mailbox contents to keep shared-hosting requests lightweight.
- IMAP mode also supports targeted lookup when PHP IMAP is available.

### Changed
- Cron remains a fallback, expiration and maintenance worker rather than the primary user-facing trigger.
- Communications 1.1.0 already polls the status API every few seconds, so no Communications update is required for this speed improvement.

## 1.10.0 — 2026-08-14
### Added
- Live Mail Testing service for `mailtest@divisiondesk.com`.
- Secure create/status API with per-test random access tokens and client rate limiting.
- IMAP or Maildir mailbox ingestion; analyzed messages are deleted after processing.
- SpamAssassin scoring adapter with automatic binary discovery.
- Daily SpamAssassin rule update service using `sa-update`, with manual fetch-driven Update Rules action.
- Authentication analysis for SPF, DKIM and DMARC from the received message.
- Configurable provider-based DNSBL and domain/URI blocklist checking.
- Message structure, URL and content checks.
- Composite DivisionDesk Inbox Probability estimate and recommendations.
- Responsive Server Mail Testing administration page.
- Encrypted Server secret vault for mailbox credentials.
- `bin/mailtest-worker.php` for cron mailbox polling, test expiration and daily rule maintenance.

### Privacy
- Raw test messages are analyzed transiently and are not stored in the DivisionDesk database.
- Mailbox messages matched to a test are deleted after analysis.
- Results retain structured findings, not the original message body.

## 1.9.0 — 2026-08-14
### Added
- Formal DivisionDesk Core release manifest/API schema with current version, absolute package URL, SHA-256, exact package size, minimum PHP version and installer compatibility metadata.
- Public `DivisionDesk-install` CLI bootstrap distribution.
- Safe source-download endpoint for the single-file `divisiondesk-install.php` browser installer.
- Browser installer source is stored outside the public execution path so visiting divisiondesk.com cannot run a client installer against the DivisionDesk Server.
- Core publish pipeline now publishes the CLI/browser installer assets carried by the verified Core package.
- Versioned Core-file verification manifests for future repair/verification tooling.
- Release contract normalizer upgrades existing `latest.json` manifests to the formal schema where possible.

### Changed
- Core Publisher now requires `DivisionDesk-install`, `divisiondesk-install.php`, and `release/core-files.json` in new Core packages.
- Legacy `scv-install` is retired and removed from the public Server when encountered.
- Installation page now documents both SSH/CLI and no-SSH browser installation, including local filesystem, FTP, FTPS, SFTP and manual ZIP fallback.
- Core post-publish verification checks the formal package URL, SHA-256 and package-size fields.

### Security
- Core ZIP validation now rejects unsafe traversal paths and Unix symlink entries.
- Browser installer is distributed as a download rather than executed on divisiondesk.com.
- FTP/FTPS/SFTP browser-install credentials remain transient to the client installer and are never stored by the DivisionDesk Server.

## 1.8.1 — 2026-08-14
### Fixed
- Server Health now loads the standard authenticated Administration bootstrap before using the database connection.
- Fixed `Undefined variable $pdo` / `Call to a member function query() on null` in `public/admin/health.php`.
- Administrator password-schema health check is now database-driver aware instead of assuming SQLite-specific PRAGMA query syntax.

### Changed
- Server Health now separates PHP/hosting startup warnings from DivisionDesk application failures.
- Added guidance that `pdo_oci`/Oracle PDO is not required by DivisionDesk and may be disabled when the Oracle client library is unavailable.

## 1.8.0 — 2026-08-14
### Added
- Product-grade public DivisionDesk.com website with Features, Installation, Store, Demo, Help, Community, Changelog and unified search.
- SEO metadata, canonical URLs, Open Graph/Twitter cards, SoftwareApplication structured data, robots.txt and sitemap.
- Persistent administrator **Remember Me** authentication with revocable hashed device tokens.
- Package lifecycle actions: Unpublish, Republish, and Unpublish & Remove while retaining historical metadata/changelog.
- Per-release cumulative changelog ingestion from package `CHANGELOG.md`.
- Public package release history and changelog presentation.
- Demo-site manager, demo package feed and bundled disposable demo client that automatically syncs Store packages.
- Public Store search/filtering and richer package detail pages.
### Changed
- Canonical DivisionDesk Server URL is `https://divisiondesk.com/`.
- Package download URLs are generated from relative `/releases/...` paths, never from filesystem paths.
- Legacy stored absolute package paths are normalized automatically.
- Public Server pages no longer use the client-site `Powered by DivisionDesk` footer.
### Fixed
- Domain moves can no longer create malformed package URLs such as `divisiondesk.com_html/cms/public/...`.
- Bootstrap installers now default to `https://divisiondesk.com`.

## 1.14.0 — 2026-08-16
- Added Licensing & Entitlements, activation lifecycle, license extension/suspension/revocation/reactivation, and signed heartbeat licensing payloads.
- Added Last Seen/inactive-client filtering and deliberate Remove Client workflow.
- Added the single-cron PHP Scheduler with locking, run history, manual run, pause/resume, and recurring jobs.
- Added Knowledge Trainer bulk uploads, ZIP training sets, URL training, bounded same-domain spidering, review queue, and recurring source monitoring.
- Added package-driven Help ingestion: documentation can ship with the release that owns it.
- Made Community and Feature Requests functional on the public DivisionDesk site, with Server moderation/triage tools.
- Introduced cohesive responsive admin/public styling and shared fetch/AJAX feedback patterns.

## 1.15.0 — Flagship UI & Accessibility
- Unified the public site and Server administration around a refined shared DivisionDesk design language.
- Rebuilt the public home and feature pages with custom reusable SVG product illustrations and clearer product storytelling.
- Added a polished administration overview and shared component styling without changing the underlying operational workflows.
- Added a Server UI Showcase to keep future screens visually consistent.
- Added persistent accessibility preferences across public and admin surfaces: standard/high/soft contrast, 100/112/125% text, relaxed line spacing, reduced motion, underlined links, stronger keyboard focus, and skip-to-content navigation.
- Accessibility preferences are browser-local and do not require an account or database migration.


## v1.17 Store licensing revision
Store access is entitlement-driven. Packages may be Free, Included, Paid, Private/Assigned or Not for Sale, with monthly, annual and lifetime price points plus optional trials. Restricted downloads require signed client authorization and short-lived download tokens. See Help: Store Pricing, Trials & Entitlements.

## 1.18.4 — Release delivery compatibility repair
- Added a self-healing release-delivery compatibility check so legacy deny rules under `public/releases` are removed when Store catalog/API traffic occurs.
- Normalizes release directories to 0755 and published release/checksum files to 0644 so Apache can serve them on restrictive hosting umasks.
- Publisher now repairs release delivery policy before publishing and normalizes permissions after placing every package archive.
- Keeps transition-direct Store downloads compatible with current Core while preserving signed/tokenized authorization endpoints for later coordinated enforcement.
Module

Communications 1.4.28

development · published · 2026-10-01T23:07:19+00:00

Fixes the Core 4.6.58 update lifecycle contract while retaining reusable mailing lists, dynamic All Members, multi-list campaign selection, CSV/manual recipient management, and recipient deduplication.

Full package changelog
## 1.4.26 - 2026-09-25
- Fix Cubicle update lifecycle: add Lifecycle::update() and run schema/endpoints/seeding during module upgrades.

# Communications 1.4.25 QA

- Added Mailing Lists management with manual recipients and CSV import.
- Added dynamic All Members audience representing everyone on the Membership Manager roster with a usable email address.
- Campaigns can combine All Members and multiple custom lists; duplicate email addresses are resolved once.
- Existing newsletter, Camp, role, manual, suppression, unsubscribe, scheduling, recurrence, analytics, and delivery flows remain in place.

# Communications 1.4.24 — Initial chat hydration performance

## 1.4.24
- Removed the unconditional browser GET to `communications-chat.php?after=0&read=0` during initial public-page load.
- Returning visitors with an existing live-chat cookie are hydrated server-side while the page is generated.
- Visitors without an existing chat cookie start with an empty client state and do not call the chat endpoint until chat is opened/used.
- Existing later chat requests, SSE, long-poll fallback, unread handling, and send behavior remain unchanged.

# Communications 1.4.23 — Member-admin alert authentication

- Staff alert badge/count endpoint now accepts Core unified authenticated principals, so a signed-in member with an assigned administrative role is not incorrectly returned 401 merely because they are not using a separate admin-account login. Permission enforcement remains `communications.inbox`.

## 1.4.23
- Newsletter subscriber audiences can target any active Core newsletter list; recipients are resolved at send time so scheduled and recurring campaigns honor current opt-ins/opt-outs.
- Campaigns now excludes `status=system` transactional/module-generated notification records from the user campaign workspace while preserving their deliveries and analytics.
- Added true recurring campaigns: daily, weekly, monthly by day-of-month or ordinal weekday, and yearly schedules with optional start date and end-by-date/end-after-count controls.
- Recurring campaigns create an immutable child run for each occurrence; recipients are resolved when the run is due, each run retains its own delivery history, and the parent campaign rolls email engagement up across runs.
- Added recurring campaign pause/resume/edit/reuse actions and clear next-send/run-count display. A recurrence that fails preflight is automatically paused rather than generating repeated failed runs every scheduler pass.
- Improved Campaigns visual hierarchy with consistent inline SVG navigation/channel/action icons, compact icon actions, schedule badges, and clearer scheduled/recurring filtering.
- Added send-time `{{communications.upcoming_events}}` dynamic content. The composer has a calendar insert control; published future Core Events are rendered when the email actually sends, so recurring event digests stay current without rebuilding the campaign.
- Campaign performance now exposes per-occurrence run history for recurring campaigns while retaining parent-level rolled-up open/click analytics. Added explicit End recurrence alongside Pause/Resume.

## 1.4.20
- Added Reuse for every saved campaign. Reuse copies campaign content, audience, channels and topic into a new unsaved campaign while deliberately excluding delivery history, analytics, status, approval and schedule.
- Added Edit for draft, scheduled and pending-approval campaigns; sent/queued history remains immutable.
- Reuse/Edit are permission-gated by `communications.compose`.

## 1.4.18 — 2026-09-09
- Redesigned Communications navigation with a dedicated module sidebar for faster access to Campaigns, Inbox, Templates, Deliverability, Providers, Live Chat, Staff Alerts and Status.
- Reorganized the Campaigns screen around a dashboard-first workflow: summary cards and campaign history appear first; **New Campaign** opens the composer only when needed.
- Added campaign status tabs and live search without changing campaign persistence, delivery, scheduling or approval behavior.
- Added per-campaign email engagement summaries directly in Campaigns: unique opens, total opens, open rate, unique clicks, total clicks and click rate.
- Added a campaign performance modal with deliveries, email deliveries, failures and engagement metrics.
- Campaign engagement reads the existing Communications tracking data that already feeds Core Analytics; no second tracking pipeline was introduced. Unique counts remain first-observed-per-delivery, while total counts include repeat tracking observations.
- Preserves all 1.4.17 delivery, transactional attachment, open/click tracking and Analytics event behavior.

## 1.4.17 — 2026-09-08
- Preserves existing first/unique `communications.email.opened` and `communications.email.clicked` analytics events.
- Records every valid tracking request as `communications.email.open_observed` / `communications.email.click_observed` so repeat engagement can be reported without inflating unique open/click rates.
- Provider tracking events are recorded on every valid request for short-term diagnostics; normalized Core Analytics remains the long-term reporting store.
- Adds a read-only email campaign/delivery directory method used by Core Analytics for campaign and recipient labels.
- Retains 1.4.16 attachment-capable transactional email delivery unchanged.

## 1.4.14 — 2026-09-04
- Added **Send Now (Don’t Save)** for one-off broadcasts that should be delivered and tracked without creating a saved campaign record.
- Added Delete actions for old campaigns. Completed delivery history is retained for analytics while pending delivery work is cancelled safely.
- **Save & Send Now** and draft **Send** now start a small immediate delivery batch in the web request instead of waiting entirely on the next scheduler interval; larger sends continue through Core's durable queue.
- Added a 60-second Communications queue-recovery job that recreates missing durable Core jobs for queued deliveries.
- Retains automatic parent campaign completion, open/click tracking, and the canonical tracked **Visit our website** footer link.
- Campaign actions update the Campaigns panel over AJAX without requiring a page refresh.

## 1.4.13
- Reworked the campaign composer around a clear normal workflow: Save Draft, Save & Schedule, or Save & Send Now.
- Moved Email Test, Preflight Analysis, and Full Deliverability Test into an optional Testing & Deliverability section so test utilities no longer look like the primary send workflow.
- Added in-place campaign-list refresh after save/schedule/send so newly saved campaigns appear immediately without a browser refresh.
- A saved draft now keeps its campaign ID in the composer; subsequent saves update that draft instead of inserting another campaign. A server-side submission token also makes duplicate AJAX/form submissions idempotent, preventing two rows even if the submit handler fires twice.
- Added a New Campaign action to deliberately clear the current saved draft and begin another campaign.
- Save & Send Now persists and queues the campaign in one action; Save & Schedule requires an explicit scheduled date/time. Approval-required campaigns are saved into the approval workflow rather than sent directly.

## 1.4.12
- Campaign status now advances from `queued` to `sent` after all deliveries complete, or `failed` after terminal delivery failure, instead of remaining permanently queued.
- Every tracked HTML email now receives a canonical `Visit our website` link immediately beside the open-tracking pixel; the link is routed through Communications click tracking.

## 1.4.11 — 2026-09-04

### Fixed
- Campaign test emails now create a Communications delivery record before MIME generation and receive the same signed per-delivery 1×1 open pixel and tracked links as bulk campaign deliveries.
- Bulk campaign tracking decoration now happens after the unsubscribe/footer HTML is assembled, so the final HTML MIME body contains the tracking pixel.
- `Tracking::decorateHtml()` now independently honors open-tracking and link-tracking flags instead of applying both whenever either was enabled.
- Test-send success/failure is recorded through Communications delivery/analytics events so real SMTP test messages can verify send → open → click behavior.

### Improved
- Campaign composer wording now clearly exposes `All active Membership Manager members in my scope` as the full scoped bulk-email audience and explains Camp, role, and manual targeting.

# Communications 1.4.10

- Preserves signed 1x1 open-pixel analytics for Communications email delivery.
- Adds independent open-pixel and link-tracking controls (`disable_open_tracking`, `disable_link_tracking`) while preserving `disable_tracking` as the master opt-out.
- Keeps first-open/first-click Analytics recording behavior unchanged.
- Core-owned email paths that bypass Communications still require the Core transactional-mail bridge and are not intercepted by this module alone.

# DivisionDesk Communications 1.4.9

- Added site-specific branding to every browser push notification.
- Push titles now include the configured Core site name rather than generic DivisionDesk branding.
- Uses the site's configured logo as the notification icon and favicon/logo as the badge when available.
- Preserves module-supplied images, icons, badges, and actions instead of overwriting them.
- Adds a default `Open` notification action when a destination URL exists and the browser/OS supports actions.
- Improved service-worker click handling for relative and subdirectory URLs.
- Retains all 1.4.2–1.4.8 concurrency, Campaigns, service-worker, VAPID, encryption, delivery, and URL-prefix fixes.

# DivisionDesk Communications 1.4.8

- Fixed browser-push links receiving the DivisionDesk installation prefix twice.
- Central push URL normalization is now idempotent: URLs already beginning with Core `basePath()` are preserved.
- Social Media alert URLs are no longer pre-expanded before the centralized normalization step.
- Retains all 1.4.2–1.4.7 performance, Campaigns, service-worker, VAPID, encryption, and push-delivery fixes.

# DivisionDesk Communications 1.4.7

- Fixed browser-push links dropping the DivisionDesk installation prefix on subdirectory sites.
- Centralized site-local push URL normalization through Core `Url::to()`.
- Social Media push alerts now explicitly normalize their inbox destination before delivery.
- Staff alert fallback links are also normalized through Core URL handling.
- Fully-qualified external URLs and special schemes remain unchanged.
- Retains all 1.4.2–1.4.6 performance, Campaigns, service-worker, VAPID, and Web Push delivery fixes.

# DivisionDesk Communications 1.4.6

- Fixed Web Push deliveries failing with `Undefined array key "urgency"` when a notification omitted an explicit urgency value.
- Social Media push alerts now explicitly use `urgency=normal` and a 24-hour TTL.
- Normalized ephemeral P-256 X/Y coordinates to exactly 32 bytes before Web Push payload encryption.
- Retains the 1.4.5 VAPID-key fix, 1.4.4 base-path service-worker fix, 1.4.3 Campaigns JS fix, and 1.4.2 concurrency fixes.

# DivisionDesk Communications 1.4.5

- Fixed Web Push enrollment failures caused by invalid-length VAPID P-256 keys.
- Generated EC X/Y coordinates and private scalar are now left-padded to exactly 32 bytes before base64url encoding.
- Push subscription discovery now validates the stored VAPID public key and returns a precise setup error if it is invalid.
- Retains the 1.4.4 service-worker base-path fix, 1.4.3 Campaigns JS fix, and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.4

- Fixed Web Push service-worker registration on installations hosted below the domain root.
- Push subscription discovery now uses Core `Url::to()` so the service worker resolves inside the active DivisionDesk installation, e.g. `/new_test_site/public/divisiondesk-push-sw.js`.
- Retains the 1.4.3 Campaigns JavaScript rendering fix and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.3

- Fixed raw JavaScript appearing as visible text at the bottom of the Campaigns screen.
- Moved Campaigns UI JavaScript from a large inline heredoc to `communications-campaigns.js`.
- Public endpoint setup now deploys and validates that asset automatically.
- Retains Communications 1.4.2 lightweight polling/session-lock fixes.

# DivisionDesk Communications 1.4.2

- Generated high-frequency alert-count, chat, and inbox API endpoints now use Core lightweight bootstrap.
- These endpoints release the PHP session immediately and skip unrelated full add-on boot work, preventing long-poll/chat traffic from blocking normal admin pages.
- Works with Core 4.6.8 single-flight alert polling to prevent request pile-ups on shared hosting.

# Changelog

## 1.4.1
- Added normalized Core Analytics events for campaign queueing, notification queueing, delivery sent/delivered/failed/suppressed, email sent/opened/clicked/failed, live-chat start/inbound messages, and staff replies/internal notes.
- Email-open Analytics is explicitly low-confidence and click Analytics medium-confidence; member/campaign context is included when available.
- Added a Social Media alert event bridge: when Social push notifications are enabled, new external social comments/messages/mentions are pushed immediately to active admin Web Push subscriptions.
- Social push delivery does not create duplicate onsite alerts; Social Media remains the canonical global alert provider.

# Communications Changelog

## 1.4.0
- Replaced fixed chat polling with SSE-first transport and automatic long-poll/short-poll fallback for shared hosting.
- Added signed 1x1 email open tracking and safe HTTP(S) click tracking for Communications deliveries.
- Email opens/clicks now update delivery timestamps and Core Analytics signals.
- Preserved unread chat state when the widget is closed.

# DivisionDesk Communications Changelog

## 1.3.0 — 2026-08-15
### DivisionDesk notification-center integration
- Unread Communications staff alerts appear in the main DivisionDesk Administration notification bell.
- The bell is hidden when there are no unread alerts.
- Clicking a Communications alert marks that alert read and opens the exact related conversation.
- Communications registers its Web Push enrollment with Core so administrators are prompted at the top of Administration when browser notifications are available but not enabled on the current device.
- Existing Inbox unread badges, email alerts, push alerts and optional SMS staff alerts remain available.

## 1.2.5 — 2026-08-15
### Messaging usability
- Fixed the admin Inbox so long conversations scroll inside the message pane instead of expanding the whole page.
- Conversation list and current thread now own independent scroll regions.
- Reply composer remains anchored at the bottom of the current conversation.
- Mobile Inbox keeps a bounded scrollable conversation list and a dedicated thread viewport.
- Replaced the very short single-tone notification beep with a softer, longer two-tone chat chime.
- The improved notification sound is used consistently for new messages on both the staff Inbox and visitor chat.

## 1.2.4 — 2026-08-15
### Live messaging workflow
- Live chat requires the visitor's name and email address.
- A staff chat reply that remains unread for two minutes is emailed to the visitor; active visitors who read it in chat do not receive a duplicate email.
- Visitor name is now required before starting live chat so staff can distinguish conversations.
- Visitor chat persists across public-page navigation; an open chat reopens on the next page, while an intentionally closed chat remains closed.
- Visitor chat polls automatically and plays a short sound when a genuinely new staff reply arrives.
- Communications Inbox is now a two-pane live messaging workspace with all conversations visible beside the current thread.
- Conversation list and current thread refresh automatically without page reload.
- Admin receives a short sound when a genuinely new inbound message arrives.
- Replies, internal notes, status changes, assignments and conversation switching are fetch-driven.
- Conversation list shows visitor name, latest-message preview, channel, status and unread count.
- Open/pending, all, and resolved conversation views are available without overwhelming the default screen.

## 1.2.3 — 2026-08-15
### Staff message alerts
- New live chat, website-form and inbound SMS messages can notify staff automatically.
- Communications Inbox shows a live unread badge in DivisionDesk administration.
- On-site staff alerts link directly to the conversation.
- Email alerts are sent for new conversations by default; Advanced can email every inbound message.
- Browser push can be enabled independently on each staff device.
- Optional SMS alerts can be sent to configured staff numbers.
- Opening a conversation marks its associated staff alerts read.
- Staff Alerts settings save with fetch and include plain-language readiness/help.

## 1.2.2 — 2026-08-15
### Critical fix
- `communications-chat.php` and all other generated Communications public endpoints are now ensured whenever the module registers.
- Upgraded installations self-heal if an earlier update did not regenerate public endpoints.
- Removed suppressed writes from endpoint generation.
- Endpoint generation now fails loudly when `public/` is unavailable/unwritable or a generated file cannot be written.
- Final required-file verification runs before endpoint generation returns success.
- Existing generated files are rewritten only when contents differ.

### Regression tests
- Fresh endpoint generation.
- Upgrade simulation beginning from the pre-chat endpoint set.
- Missing-chat self-healing.
- Idempotent regeneration.
- Failure-path test proving an invalid public path no longer silently succeeds.

## 1.2.1 — 2026-08-15
### Critical upgrade fix
- Replaced the old single-table `Schema::ensure()` shortcut with a sequential migration ledger.
- Existing Communications installations now run every missing migration in natural version order instead of returning early when the original templates table already exists.
- Live-chat migration `003_live_chat.php` therefore runs correctly during module update, not only on fresh installs.
- Migration failures are transactional where supported and identify the exact migration that failed.
- Schema completion is checked after migrations.

### Packaging
- `addon.json` and `manifest.json` explicitly declare `package_type: module`.
- Version bumped to 1.2.1 so it cannot collide with the rejected/staged 1.2.0 package history.

## 1.2.0 — 2026-08-15
### Completed
- Site-wide live chat is automatically injected on public pages when Communications is enabled; no floating widget placement is required.
- Chat uses a speech-bubble icon, fetch-driven history/send/poll, secure guest session cookie, unread badge, mobile full-screen UI, office hours/away message, identity requirements, optional avatar/accent and path exclusions.
- Chat conversations and staff replies are fully integrated with the Communications Inbox.
- Contact/Message widget now provides Contact Card and fetch-driven Inline Form layouts; obsolete Floating Button layout removed.
- SMS provider validation now includes stored secrets; Providers includes real SMS test, segment count and administrator-configured approximate cost.
- Web Push VAPID key generation is exposed when the required runtime library is available.
- Reports include normalized provider callback outcomes.
- System Status page explicitly reports operational, configuration-required, dependency-required, disabled and unsupported-external-workflow states.

### Compatibility
- Requires DivisionDesk Core 3.6.4 for automatic public-page integration.
- Coordinated DivisionDesk Server 1.11.4 adds bounded independent DKIM verification and DMARC evaluation via aligned DKIM.

## 1.1.4 — 2026-08-14
### Fixed
- Full Deliverability create/status calls allow up to 20 seconds for bounded DivisionDesk Server analysis.
- Rebuilt directly from the publisher-validated Communications 1.1.2 package to eliminate staging ambiguity from the rejected 1.1.3 package.

## 1.1.2 — 2026-08-14
### Improved
- Deliverability modal now displays **Test Coverage** separately from Inbox Probability.
- Unavailable SpamAssassin and reputation checks are shown as `Not checked`/`Unable to check` rather than visually implying failure.
- Authentication shows evidence-aware states: Pass, Fail, Signature Present, Policy Present, or Unknown.
- Content & Links now includes a detailed reputation-query report showing provider, tested IP/domain, DNS response, interpretation and query.
- Reputation results distinguish **Clear**, **Listed**, and **Unable to Check**.
- Recommendations explain excluded/unavailable signals instead of treating them as negative delivery evidence.

## 1.1.1 — 2026-08-14
### Fixed
- Deliverability results now render as a true fixed overlay instead of appearing at the bottom of the Campaigns page.
- Mobile view becomes a full-screen sheet with scrollable details.
- Page scrolling is locked while the modal is open.
- Restored the `TestEmail::send(..., $options)` signature needed to attach the secure live-test correlation header.
- Live status displays mailbox-poll warnings instead of silently waiting forever.

## 1.1.0 — 2026-08-14
### Added
- Instant campaign Preflight Analysis.
- Full Deliverability Test through `mailtest@divisiondesk.com`.
- Secure DivisionDesk Server create/status test workflow.
- Actual campaign is sent through the site's configured SMTP transport with a correlation header.
- Responsive circular Inbox Probability gauge with gradual deep-red → red → orange → yellow → green progression.
- Large desktop modal becomes a full-screen mobile sheet.
- Live polling states: sending, waiting, received/analyzing, complete.
- SpamAssassin, authentication, blocklist, structure, content/link and recommendations tabs.
- Fetch-driven workflow; Campaign composer never reloads during testing.

### Changed
- Inbox Probability is explicitly presented as a DivisionDesk estimate, not a receiving-provider guarantee.

## 1.0.7 — 2026-08-14

### Fixed
- Fixed Campaign fetch actions returning Administration HTML before JSON.
- AJAX Campaign requests now authenticate/authorize without rendering `AdminUi::start()` first.
- CSRF verification is handled inside the JSON request error path.
- AJAX responses are explicitly JSON and `Cache-Control: no-store`.

### Diagnostics
- If a future fetch request receives non-JSON content, DivisionDesk shows a short excerpt of the actual HTTP response instead of directing the administrator to a server log that may contain no error.

## 1.0.6 — 2026-08-14

### Fixed
- Fixed `SMTP host and a valid envelope/From email are required` when Core has a valid From address but the optional envelope sender is blank.
- Empty `envelope_from` now correctly falls back to Core `from_email`.

### Changed
- Campaign **Send Email Test** and **Save Campaign** now use `fetch()` and display success/errors in place.
- Transport/validation errors no longer refresh the Campaigns page or clear the composer.
- Non-AJAX fallback restores posted campaign fields after a server-rendered error.
- Submit buttons show a busy state and duplicate submissions are prevented.

### UX direction
- Fetch/AJAX-style in-place actions are the preferred DivisionDesk interaction model where practical.
- User-entered form data should survive errors rather than returning to blank forms.

## 1.0.5 — 2026-08-14

### Fixed
- Fixed campaign test failure `List-Unsubscribe must be HTTPS or mailto.`
- Core relative/base-path URLs are no longer inserted directly into email headers.
- HTTPS web requests automatically establish a canonical DivisionDesk public site URL for Communications.
- Background campaign jobs reuse the stored canonical HTTPS site URL.
- Local/LAN/non-HTTPS installations fall back to a standards-valid `mailto:` List-Unsubscribe target instead of emitting an invalid relative URL.
- `List-Unsubscribe-Post: List-Unsubscribe=One-Click` remains limited to actual HTTPS unsubscribe endpoints.
- Avoids duplicating the Core base path when building absolute unsubscribe URLs.

### Diagnostics
- Communications Providers and Deliverability now show whether bulk email is using HTTPS one-click unsubscribe or the mailto fallback.

## 1.0.4 — 2026-08-14

### Fixed
- Communications now reads the existing DivisionDesk Core **Email Delivery** configuration for SMTP and From settings.
- Campaign Email Test no longer incorrectly reports SMTP as unconfigured when Core SMTP is already working.
- SMTP password is consumed from Core Mailer configuration; Communications no longer expects a duplicate `communications.smtp.password`.
- Blank EHLO/HELO remains blank in configuration and is resolved automatically by the mail transport at connection time.
- Campaign and queued email failures now identify the specific missing Core Email Delivery setting.

### Changed
- Communications → Providers no longer presents a second SMTP configuration form.
- The Providers page shows Core email readiness/status and links directly to the global Email Delivery page.
- Communications-owned provider settings are now limited to SMS and Web Push.

## 1.0.3 — 2026-08-14

### Fixed
- Fixed Campaigns buttons appearing to do nothing with Chrome error `An invalid form control with name='push_url' is not focusable`.
- Push URL, image, icon and badge fields now accept DivisionDesk template variables such as `{{site.url}}` without HTML5 URL validation blocking form submission.
- **Send Email Test** now uses `formnovalidate` so hidden/unrelated campaign channel fields cannot prevent a transport/template test from reaching PHP.

## 1.0.2 — 2026-08-14

### Fixed
- Built-in templates now self-heal if a previous installation or upgrade left `communications_templates` empty.
- Added upgrade migration 002 so 1.0.2 reliably invokes the idempotent template seeder after upgrading.
- Module registration, Campaigns, and Templates defensively restore missing built-ins without overwriting existing customized templates.
- Corrected Campaign list column rendering for topic, channels, schedule, deliveries and actions.

### Added
- Rebuilt Campaigns as a polished multi-channel composer.
- Template selection now immediately loads the template subject, styled HTML, plain-text version, SMS text and push payload into the composer.
- Rich HTML email editor with formatting controls and HTML-source toggle.
- Sandboxed email preview and push-notification preview.
- Immediate single-recipient SMTP campaign test using the production Communications email builder, including multipart HTML/text, Date, Message-ID, List-Unsubscribe and one-click unsubscribe headers.
- Improved channel cards/tabs, SMS character count, audience/timing controls and contextual deliverability guidance.
- Redesigned Template Library with cards, statistics, editor, and Restore Missing Built-ins control.
- Upgraded built-in Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Events, Dues Renewal, Welcome, Login Code, Application Status and Contact Response templates with polished inline email styling.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer; Core 3.6.1 is recommended.

## 1.0.1 — 2026-08-14

### Fixed
- Fixed fresh installation failure: `SQLSTATE[HY000]: General error: 1 no such table: communications_templates`.
- Communications now ensures its schema exists before seeding built-in templates.
- Install, enable and update entry points are safe against a partially completed 1.0.0 installation.
- Existing `CREATE TABLE IF NOT EXISTS` migration statements make recovery non-destructive.

### Compatibility
- Works with DivisionDesk Core 3.6.0 and newer.
- Core 3.6.1 separately corrects the generic module lifecycle ordering for all modules.

## 1.0.0 — 2026-08-14

### Added
- Multi-channel campaign model for Email, SMS, Push and on-site delivery.
- Membership Manager audience adapter with active-member, Camp and role targeting.
- Shared background delivery jobs using DivisionDesk Core 3.6 Job Queue.
- Multipart HTML/plain-text email construction with Date, Message-ID, Reply-To, List-ID, List-Unsubscribe and one-click unsubscribe headers where appropriate.
- Non-transactional email footer with physical/site address and unsubscribe link.
- Email header-injection safeguards.
- Deliverability Center with SMTP, sender, SPF and DMARC checks plus DKIM guidance.
- Suppression system for opt-outs, provider failures and invalid destinations.
- Built-in communication templates: Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Event Announcement, Event Reminder, Registration Confirmation, Dues Renewal, Welcome, Login Code, Application Status and Contact Response.
- SMS provider abstraction with Twilio, Amazon SNS and Telnyx outbound adapters.
- Normalized Twilio errors for invalid, landline/non-SMS, unreachable and opted-out numbers.
- Automatic permanent SMS suppression for selected permanent provider failures.
- STOP/START handling for inbound SMS.
- Incoming SMS webhook/conversation handling for Twilio and Telnyx.
- Standards-oriented Web Push subscription database and service worker.
- VAPID Web Push adapter integration point.
- Rich push payload model: title, body, URL, image, icon, badge, actions, tag, TTL, urgency and require-interaction.
- Unified Conversations Inbox for website/contact/SMS messages.
- Public Contact Us / Website Messaging system.
- Member Communication Preferences page.
- Contact, Announcement and Communication Preferences widgets.
- NotificationService API for other DivisionDesk modules to queue transactional or bulk notifications.
- Notification Rule trigger/action foundation.
- Provider settings using Core encrypted Secret Vault.
- Delivery reports, provider-event history and configurable retention foundation.

### Security
- Provider secrets are encrypted by Core 3.6 Secret Vault.
- Twilio webhook signatures are validated before incoming events are trusted.
- Telnyx Ed25519 webhook verification is supported when a public verification key is configured.
- Email header values reject CR/LF injection.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer.
Module

SCV Operations 3.0.21

development · published · 2026-10-01T22:43:31+00:00

Packaging repair for Core 4.6.58: restores the legacy membership application Platform/CoreBridge.php required by the SCV Operations bootstrap; preserves 3.0.20 acceptance changes.

Module

Events 1.1.28

development · published · 2026-10-01T22:43:29+00:00

Fix Core 4.6.58 update lifecycle contract: Update::update() is now the update entry point; preserves camp-scoped event permissions and prior installation fixes.

Full package changelog
# 1.1.26 QA

- Fix installation failure caused by `use PDO;` in the global-namespace event-scope migration.
- Preserve 1.1.25 Camp-scoped event authorization and migration behavior.

# Events 1.1.25

- Adds organization scope to events. Existing events converge to Division/default.
- Camp Commander and Camp Adjutant may create, edit, publish/archive, and delete only events owned by their own Camp.
- Camp-scoped authorization is enforced server-side for save, cancel/archive, and delete operations.
- Camp officers see only their Camp events in Events administration; Division event administrators retain Division-wide authority.
- Camp event saves use the module-owned scoped save action instead of the legacy global Core save endpoint.

# Events 1.1.24
- Registration Closes remains a configurable date/time.
- Leaving it blank now explicitly means registration closes when the event begins.
- Existing registration-enabled events with no close time are converged to their event start so Core's server-side registration endpoint rejects late/direct submissions.
- The module editor synchronizes Core and Events registration timing columns after each save.
- Public registration shows a closed/not-yet-open message instead of a form outside the allowed window.
- `Register Now` is not shown after registration closes.
- Verified public Events list/upcoming/featured queries already exclude occurrences once their start time has passed.
- No Core update required.

# Events 1.1.23
- FIX: The blank public `Events` title area is now suppressed using the actual DivisionDesk Builder heading markup (`cms-block--heading`) on event-detail pages.
- The previous 1.1.22 selector looked for a `cms-hero`, which is not what this page uses; therefore it could never hide the title shown in the test screenshot.
- The Events listing page remains unchanged.
- Retains 1.1.22 tab-scroll, registration UI, and Schedule editor toolbar fixes.
- No Core change.

# Events 1.1.22
- FIX: Public tab clicks no longer jump the browser back to the top of the event card; the native tab radio state is fixed to the viewport rather than positioned at the article top.
- FIX: Event-detail pages hide the generic CMS `Events` hero/blank title area. The Events listing page is unchanged.
- FIX: Schedule rich-text toolbar buttons have explicit contrasting backgrounds/text so formatting icons remain visible.
- FIX: `Register & Pay Online` is shown only when the installed Finance module exposes the supported Events checkout contract.
- Paid Events registrations work with Finance 1.2.9+; `Register — Pay Later` remains available independently.
- No Core changes.

# Events 1.1.21
- FIX: Public Overview / Schedule / Location / Registration tabs no longer depend on JavaScript. They use native radio/label state plus CSS, so exactly one panel is selected without a JS tab handler.
- FIX: Register Now switches directly to the Registration panel using that same native mechanism.
- FIX: Corrected an undefined `$eventId` reference in the generated registration JavaScript; the real event ID is now used.
- FIX: Standalone Registration Button widget no longer inherits tab-only hidden styling.
- No Core, Finance, or Membership Manager changes.

# Events 1.1.20
- Removed attendee type selection from the new public registration flow.
- Member number and Camp name/number are available on every registration and are optional except member number on explicitly members-only events.
- Additional Guests is built in and defaults to $0 additional registration fee.
- Event admins may explicitly apply the base registration fee to each additional guest.
- Add-on quantities are independent of primary registrant/guest count.
- Blank add-on quantity means zero.
- Quantity add-ons with per-item choices allow blank choices after a confirmation warning.
- Added a canonical Core rich-text Schedule editor and public Schedule rendering.
- Preserves historical attendee-type data for existing registrations.
- Requires Core 4.6.12+.

# Events 1.1.19

- Public event tabs are now genuinely mutually exclusive. Overview, Schedule, Location and Registration occupy the same content region; inactive panels are both hidden and `display:none`.
- `Register Now` activates the Registration panel instead of appending/scrolling to a second copy of event content.
- Attendee types may be removed from active configuration even when historical registrations reference them; in that case the type is archived and history is preserved.
- An active attendee type named `Guest` automatically creates an `Additional Guests` registration control using that Guest price. Selecting 2 guests creates exactly 2 required guest-name fields.
- Priced Select/Radio options with choices are normalized to `quantity_choice`, so a Banquet priced per person gets a quantity selector and one Beef/Chicken/etc. selector per purchased unit.
- Reducing a guest/option quantity removes excess DOM controls, so hidden stale names/choices are not submitted.
- Requires Core 4.6.11+ because Core owns authoritative server-side quantity normalization and pricing.

# Events 1.1.18
- Registration is now a true event tab instead of content appended below Overview.
- Primary attendee collects full name, address, phone and email; member-only registrations also require member number and Camp name/number.
- Logged-in members auto-fill from the Membership Manager provider when available.
- Adds Guest Names options: selecting quantity N creates exactly N guest-name fields.
- Adds Quantity + per-item choice options: quantity N creates exactly N choice selectors, e.g. Beef/Chicken for each meal.
- Reducing a quantity removes and clears excess guest/choice inputs immediately.
- Quantity pricing updates live and zero quantity means no charge.
- Hides legacy duplicate `Registration Fee` add-ons when attendee type pricing already provides the base registration price.
- Retains 1.1.17 pay-now/pay-later and duplicate-submit fixes.

# Events 1.1.17
- Fixes duplicate registrations caused by Core and Events both submitting the same form.
- Fixes Save/Publish redirecting to legacy Core Events admin.
- Adds Register & Pay Online / Register — Pay Later and a live registration/add-on/total breakdown.
- Finance completion marks the matching registration paid/confirmed.
- My Events matches member ID or email and is moved before the site footer.
- Retains 1.1.16 toggle persistence and 1.1.15 rich public detail restoration.

# Events 1.1.16

- Fixes the Events module editor Registration switch turning itself back off after Save.
- Core `registration_enabled` and Events `registration_mode` are now explicitly synchronized.
- The module's post-save integration action writes both fields, so public registration becomes available immediately after enabling it.
- Event reads treat Core's `registration_enabled` compatibility field as authoritative when an older/stale `registration_mode` disagrees.
- Waitlist state is also carried through the same module extras save.
- All 1.1.15 public detail/card/routing and 1.1.13 registration/check-in/refund functionality is retained.

# Events 1.1.15

- Rebuilt from the untouched Events 1.1.13 package, not from 1.1.14.
- Preserves the 1.1.13 rich registration, QR/check-in, cancellation/refund, My Events, attendee/options and Finance integration code.
- Adds only the missing `days()`, `daysUntil()` and `startingPrice()` helpers required by the existing public detail renderer.
- Upcoming/Next/Featured event cards are styled, clickable and show `Cost: Starting at $xx.xx` for paid events.
- `/events?event=ID` now hands the Events page into the existing full Event Detail / Registration renderer instead of looping to the same list card.
- Adds narrow duplicate-submit protection to the legacy and current event editors.

# Changelog

## 1.1.13

- Fixed the false Core "Check-in code is invalid" toast after a successful short confirmation-code check-in by removing the native form-submit path entirely. The Events check-in control now uses one explicit AJAX action for short codes and only calls Core directly for signed credentials.
- Quick Actions on the Events dashboard is now a working no-JavaScript dropdown with direct links to Check-in, Registrations, Attendees, Reports and Settings.
- Removed the duplicated Core module title/card from Events administration and expanded the Events application shell to the available admin width without modifying Core.
- Expanded My Events management: members can open registration details, add guests through Core Registration 2.0 (including required guest options/add-ons), add available zero-cost options, remove options only when cancellation/refund policy allows, and cancel the full registration when permitted.
- Paid option additions are intentionally blocked before mutation when Core/Finance has no safe incremental-charge contract; the module will not silently add an unpaid charge to an already-paid registration.
- Paid refundable option removal creates an itemized refund request for Finance review instead of silently changing historical payment data.

## 1.1.12
- Audited against DivisionDesk Core 4.4.4 without changing Core.
- Fixed camera flow so permission is requested before decoder capability checks; added native BarcodeDetector + jsQR fallback scanning.
- Check-in now accepts a full QR URL, signed token, or visible confirmation code such as `761A88ED8D`.
- Bypassed the Core subdirectory QR double-prefix issue in the Events public flow by generating a correct module-owned QR from the signed credential.
- Added SDK-based `/my-events` management/cancellation controls for signed-in members.
- Aligned runtime data access with Core Registration 2.0 (`first_name`/`last_name`, `confirmed`/`waitlisted`, `price_cents`, `event_registration_options`, `event_registration_answers`).
- Refund calculations now use Core paid totals and answer price snapshots when available.
- Prevented Events uninstall from dropping Core-owned event/registration tables.

## 1.1.11
- Added attendee self-cancellation using confirmation code + registration email, with per-event cancellation controls and cutoff date.
- Added event-level refund modes plus per-attendee-type and per-option refund policies (inherit/refundable/nonrefundable/manual).
- Paid cancellations create auditable itemized refund requests; Events never moves money directly and leaves actual refund processing to Core/Finance.
- Added optional automatic waitlist promotion when a confirmed registration cancels.
- Reworked confirmation URL normalization so the configured DivisionDesk base path is never prepended twice by Events.
- Expanded schema convergence and Diagnostics for cancellation/refund fields and refund-request storage.
- Documented that the QR image on Core's confirmation/badge page is Core-owned; Events Check-in safely extracts the signed token even if a scanned QR contains a URL.

## 1.1.9
- Prevented duplicate public registration submissions with a single raw same-origin request, submit locking, button disabling, and a short post-success lock.
- Public registration now explicitly renders every active option/add-on and labels each one Required or Optional; only required fields receive browser validation.
- Successful registration stays in the Events registration experience rather than automatically following Core legacy redirects.
- Confirmation URLs returned by Core are normalized to the configured DivisionDesk public base path for subdirectory installs.
- QR check-in accepts a raw signed credential or extracts token/credential/checkin_token/code values from a scanned QR URL.
- Removed the module link to undocumented `/events-badge.php`, which could produce a 404; registrations now link to the supported Check-in workspace.

## 1.1.8
- Removed duplicate Core/page heading presentation from Events module pages and widened the Events workspace.
- Published one-off events are now immediately discoverable by public Events widgets even if an occurrence row has not yet been materialized.
- Added an in-module public event preview so administrators can test the exact public event/registration experience before placing widgets.
- The Registration Button widget now resolves the selected/next published event and exposes a working registration flow instead of an orphan anchor.
- Event presentation fields (summary, featured image, city/state, timezone, all-day/featured flags) are persisted after the frozen Core save contract through an Events Smart Action.
- Public widget queries now fall back safely to base event dates when occurrence materialization is not available.

- Made event options/add-ons truly optional and removed invalid nested forms.
- Added multiple option/type creation controls and remove actions.
- Added cancel/archive and guarded permanent delete event actions.
- Kept successful saves inside the polished Events module editor.
- Expanded responsive layout to a centered wide workspace instead of a cramped Core column.

## 1.1.6
- Full runtime schema convergence for registration types, registration fields, and categories, including active/sort_order and every column referenced by current queries.
- Diagnostics/schema health now verifies those query-critical columns before reporting current.

# Changelog

## 1.1.6
- Fixed Dashboard/Events/Check-in compatibility with Core-created event rows that use `location` rather than `location_name`.
- Added Core 4.3.4 event-contract compatibility fields non-destructively and synchronized legacy display fields.
- Fixed partial output-buffer leakage so a caught page exception no longer duplicates the Events rail/layout.
- Event saves now return to the DivisionDesk Events module editor instead of the legacy Core `/events-admin.php` screen.
- Registration type/option saves stay inside the module UI instead of following Core legacy redirects.
- Removed negative-margin module layout behavior that could collide with the Core admin shell.
- Diagnostics now verifies both Core event-contract fields and Events display fields.

## 1.1.4
- Added request-time schema health checking and idempotent self-healing so Store replacements no longer depend on Install/Update lifecycle hooks.
- Schema repair directly converges missing Events/Registration 2.0 tables and columns without deleting existing event data.
- Diagnostics exposes automatic repair failures and retains the explicit Repair / Verify Events Schema Smart Action.
- Schema version is verified and recorded as 1.1.4 only after required objects are confirmed present.

## 1.1.2
- Stabilized Dashboard, Venues, Categories and Settings with defensive data access.
- Added module-owned exception handling so useful errors are visible instead of being swallowed by the Core page wrapper.
- Added Diagnostics page for database driver, schema version, required tables and Registration 2.0 columns.
- Added migration 003 to verify/repair required v1.1 schema columns and record schema version 1.1.2.
- Preserved the approved Events v1.1 admin visual system and Platform 1.1 API/SDK architecture.

# Events Changelog

## 1.1.0 — 2026-08-28
- Rebuilt administration around Developer Platform 1.1 module-owned admin pages and the approved Events dashboard visual language.
- Added Registration 2.0 attendee types, priced options/add-ons, capacities, waitlists and member-only flags.
- Added QR/manual check-in workspace and registration schema fields for signed check-in credentials, confirmation codes and check-in timestamps.
- Added Reports, Attendees, Waitlists, Venues, Settings and API workspaces.
- Added setup wizard, dashboard contribution, search provider, Smart Action, integration listeners and current SDK job registration.
- Added public Event Detail / Registration and Registration Button Builder widgets.
- Event mutations use Core Events / Registration 2.0 endpoints; payments/refunds remain owned by central Finance/Payments integration.
- Removed legacy standalone admin chrome from the primary experience.

## 1.0.0 — 2026-08-14
- Initial Events module baseline.

## 1.1.2
- Schema repair release: install/update now explicitly converges partial Events schemas.
- Creates missing categories, venues, settings, registration fields and registration types tables.
- Adds missing Registration 2.0 columns including registration_mode, amounts, confirmation and QR check-in fields.
- Adds Diagnostics Repair / Verify Events Schema action.
- Clarifies recurring-event generation horizon setting.
Module

Events 1.1.27

development · published · 2026-10-01T22:36:30+00:00

Adds the required Events Lifecycle::update() hook for Cubicle updates while preserving the 1.1.26 strict-PHP migration fix and Camp Commander/Adjutant scoped event authorization.

Full package changelog
# 1.1.26 QA

- Fix installation failure caused by `use PDO;` in the global-namespace event-scope migration.
- Preserve 1.1.25 Camp-scoped event authorization and migration behavior.

# Events 1.1.25

- Adds organization scope to events. Existing events converge to Division/default.
- Camp Commander and Camp Adjutant may create, edit, publish/archive, and delete only events owned by their own Camp.
- Camp-scoped authorization is enforced server-side for save, cancel/archive, and delete operations.
- Camp officers see only their Camp events in Events administration; Division event administrators retain Division-wide authority.
- Camp event saves use the module-owned scoped save action instead of the legacy global Core save endpoint.

# Events 1.1.24
- Registration Closes remains a configurable date/time.
- Leaving it blank now explicitly means registration closes when the event begins.
- Existing registration-enabled events with no close time are converged to their event start so Core's server-side registration endpoint rejects late/direct submissions.
- The module editor synchronizes Core and Events registration timing columns after each save.
- Public registration shows a closed/not-yet-open message instead of a form outside the allowed window.
- `Register Now` is not shown after registration closes.
- Verified public Events list/upcoming/featured queries already exclude occurrences once their start time has passed.
- No Core update required.

# Events 1.1.23
- FIX: The blank public `Events` title area is now suppressed using the actual DivisionDesk Builder heading markup (`cms-block--heading`) on event-detail pages.
- The previous 1.1.22 selector looked for a `cms-hero`, which is not what this page uses; therefore it could never hide the title shown in the test screenshot.
- The Events listing page remains unchanged.
- Retains 1.1.22 tab-scroll, registration UI, and Schedule editor toolbar fixes.
- No Core change.

# Events 1.1.22
- FIX: Public tab clicks no longer jump the browser back to the top of the event card; the native tab radio state is fixed to the viewport rather than positioned at the article top.
- FIX: Event-detail pages hide the generic CMS `Events` hero/blank title area. The Events listing page is unchanged.
- FIX: Schedule rich-text toolbar buttons have explicit contrasting backgrounds/text so formatting icons remain visible.
- FIX: `Register & Pay Online` is shown only when the installed Finance module exposes the supported Events checkout contract.
- Paid Events registrations work with Finance 1.2.9+; `Register — Pay Later` remains available independently.
- No Core changes.

# Events 1.1.21
- FIX: Public Overview / Schedule / Location / Registration tabs no longer depend on JavaScript. They use native radio/label state plus CSS, so exactly one panel is selected without a JS tab handler.
- FIX: Register Now switches directly to the Registration panel using that same native mechanism.
- FIX: Corrected an undefined `$eventId` reference in the generated registration JavaScript; the real event ID is now used.
- FIX: Standalone Registration Button widget no longer inherits tab-only hidden styling.
- No Core, Finance, or Membership Manager changes.

# Events 1.1.20
- Removed attendee type selection from the new public registration flow.
- Member number and Camp name/number are available on every registration and are optional except member number on explicitly members-only events.
- Additional Guests is built in and defaults to $0 additional registration fee.
- Event admins may explicitly apply the base registration fee to each additional guest.
- Add-on quantities are independent of primary registrant/guest count.
- Blank add-on quantity means zero.
- Quantity add-ons with per-item choices allow blank choices after a confirmation warning.
- Added a canonical Core rich-text Schedule editor and public Schedule rendering.
- Preserves historical attendee-type data for existing registrations.
- Requires Core 4.6.12+.

# Events 1.1.19

- Public event tabs are now genuinely mutually exclusive. Overview, Schedule, Location and Registration occupy the same content region; inactive panels are both hidden and `display:none`.
- `Register Now` activates the Registration panel instead of appending/scrolling to a second copy of event content.
- Attendee types may be removed from active configuration even when historical registrations reference them; in that case the type is archived and history is preserved.
- An active attendee type named `Guest` automatically creates an `Additional Guests` registration control using that Guest price. Selecting 2 guests creates exactly 2 required guest-name fields.
- Priced Select/Radio options with choices are normalized to `quantity_choice`, so a Banquet priced per person gets a quantity selector and one Beef/Chicken/etc. selector per purchased unit.
- Reducing a guest/option quantity removes excess DOM controls, so hidden stale names/choices are not submitted.
- Requires Core 4.6.11+ because Core owns authoritative server-side quantity normalization and pricing.

# Events 1.1.18
- Registration is now a true event tab instead of content appended below Overview.
- Primary attendee collects full name, address, phone and email; member-only registrations also require member number and Camp name/number.
- Logged-in members auto-fill from the Membership Manager provider when available.
- Adds Guest Names options: selecting quantity N creates exactly N guest-name fields.
- Adds Quantity + per-item choice options: quantity N creates exactly N choice selectors, e.g. Beef/Chicken for each meal.
- Reducing a quantity removes and clears excess guest/choice inputs immediately.
- Quantity pricing updates live and zero quantity means no charge.
- Hides legacy duplicate `Registration Fee` add-ons when attendee type pricing already provides the base registration price.
- Retains 1.1.17 pay-now/pay-later and duplicate-submit fixes.

# Events 1.1.17
- Fixes duplicate registrations caused by Core and Events both submitting the same form.
- Fixes Save/Publish redirecting to legacy Core Events admin.
- Adds Register & Pay Online / Register — Pay Later and a live registration/add-on/total breakdown.
- Finance completion marks the matching registration paid/confirmed.
- My Events matches member ID or email and is moved before the site footer.
- Retains 1.1.16 toggle persistence and 1.1.15 rich public detail restoration.

# Events 1.1.16

- Fixes the Events module editor Registration switch turning itself back off after Save.
- Core `registration_enabled` and Events `registration_mode` are now explicitly synchronized.
- The module's post-save integration action writes both fields, so public registration becomes available immediately after enabling it.
- Event reads treat Core's `registration_enabled` compatibility field as authoritative when an older/stale `registration_mode` disagrees.
- Waitlist state is also carried through the same module extras save.
- All 1.1.15 public detail/card/routing and 1.1.13 registration/check-in/refund functionality is retained.

# Events 1.1.15

- Rebuilt from the untouched Events 1.1.13 package, not from 1.1.14.
- Preserves the 1.1.13 rich registration, QR/check-in, cancellation/refund, My Events, attendee/options and Finance integration code.
- Adds only the missing `days()`, `daysUntil()` and `startingPrice()` helpers required by the existing public detail renderer.
- Upcoming/Next/Featured event cards are styled, clickable and show `Cost: Starting at $xx.xx` for paid events.
- `/events?event=ID` now hands the Events page into the existing full Event Detail / Registration renderer instead of looping to the same list card.
- Adds narrow duplicate-submit protection to the legacy and current event editors.

# Changelog

## 1.1.13

- Fixed the false Core "Check-in code is invalid" toast after a successful short confirmation-code check-in by removing the native form-submit path entirely. The Events check-in control now uses one explicit AJAX action for short codes and only calls Core directly for signed credentials.
- Quick Actions on the Events dashboard is now a working no-JavaScript dropdown with direct links to Check-in, Registrations, Attendees, Reports and Settings.
- Removed the duplicated Core module title/card from Events administration and expanded the Events application shell to the available admin width without modifying Core.
- Expanded My Events management: members can open registration details, add guests through Core Registration 2.0 (including required guest options/add-ons), add available zero-cost options, remove options only when cancellation/refund policy allows, and cancel the full registration when permitted.
- Paid option additions are intentionally blocked before mutation when Core/Finance has no safe incremental-charge contract; the module will not silently add an unpaid charge to an already-paid registration.
- Paid refundable option removal creates an itemized refund request for Finance review instead of silently changing historical payment data.

## 1.1.12
- Audited against DivisionDesk Core 4.4.4 without changing Core.
- Fixed camera flow so permission is requested before decoder capability checks; added native BarcodeDetector + jsQR fallback scanning.
- Check-in now accepts a full QR URL, signed token, or visible confirmation code such as `761A88ED8D`.
- Bypassed the Core subdirectory QR double-prefix issue in the Events public flow by generating a correct module-owned QR from the signed credential.
- Added SDK-based `/my-events` management/cancellation controls for signed-in members.
- Aligned runtime data access with Core Registration 2.0 (`first_name`/`last_name`, `confirmed`/`waitlisted`, `price_cents`, `event_registration_options`, `event_registration_answers`).
- Refund calculations now use Core paid totals and answer price snapshots when available.
- Prevented Events uninstall from dropping Core-owned event/registration tables.

## 1.1.11
- Added attendee self-cancellation using confirmation code + registration email, with per-event cancellation controls and cutoff date.
- Added event-level refund modes plus per-attendee-type and per-option refund policies (inherit/refundable/nonrefundable/manual).
- Paid cancellations create auditable itemized refund requests; Events never moves money directly and leaves actual refund processing to Core/Finance.
- Added optional automatic waitlist promotion when a confirmed registration cancels.
- Reworked confirmation URL normalization so the configured DivisionDesk base path is never prepended twice by Events.
- Expanded schema convergence and Diagnostics for cancellation/refund fields and refund-request storage.
- Documented that the QR image on Core's confirmation/badge page is Core-owned; Events Check-in safely extracts the signed token even if a scanned QR contains a URL.

## 1.1.9
- Prevented duplicate public registration submissions with a single raw same-origin request, submit locking, button disabling, and a short post-success lock.
- Public registration now explicitly renders every active option/add-on and labels each one Required or Optional; only required fields receive browser validation.
- Successful registration stays in the Events registration experience rather than automatically following Core legacy redirects.
- Confirmation URLs returned by Core are normalized to the configured DivisionDesk public base path for subdirectory installs.
- QR check-in accepts a raw signed credential or extracts token/credential/checkin_token/code values from a scanned QR URL.
- Removed the module link to undocumented `/events-badge.php`, which could produce a 404; registrations now link to the supported Check-in workspace.

## 1.1.8
- Removed duplicate Core/page heading presentation from Events module pages and widened the Events workspace.
- Published one-off events are now immediately discoverable by public Events widgets even if an occurrence row has not yet been materialized.
- Added an in-module public event preview so administrators can test the exact public event/registration experience before placing widgets.
- The Registration Button widget now resolves the selected/next published event and exposes a working registration flow instead of an orphan anchor.
- Event presentation fields (summary, featured image, city/state, timezone, all-day/featured flags) are persisted after the frozen Core save contract through an Events Smart Action.
- Public widget queries now fall back safely to base event dates when occurrence materialization is not available.

- Made event options/add-ons truly optional and removed invalid nested forms.
- Added multiple option/type creation controls and remove actions.
- Added cancel/archive and guarded permanent delete event actions.
- Kept successful saves inside the polished Events module editor.
- Expanded responsive layout to a centered wide workspace instead of a cramped Core column.

## 1.1.6
- Full runtime schema convergence for registration types, registration fields, and categories, including active/sort_order and every column referenced by current queries.
- Diagnostics/schema health now verifies those query-critical columns before reporting current.

# Changelog

## 1.1.6
- Fixed Dashboard/Events/Check-in compatibility with Core-created event rows that use `location` rather than `location_name`.
- Added Core 4.3.4 event-contract compatibility fields non-destructively and synchronized legacy display fields.
- Fixed partial output-buffer leakage so a caught page exception no longer duplicates the Events rail/layout.
- Event saves now return to the DivisionDesk Events module editor instead of the legacy Core `/events-admin.php` screen.
- Registration type/option saves stay inside the module UI instead of following Core legacy redirects.
- Removed negative-margin module layout behavior that could collide with the Core admin shell.
- Diagnostics now verifies both Core event-contract fields and Events display fields.

## 1.1.4
- Added request-time schema health checking and idempotent self-healing so Store replacements no longer depend on Install/Update lifecycle hooks.
- Schema repair directly converges missing Events/Registration 2.0 tables and columns without deleting existing event data.
- Diagnostics exposes automatic repair failures and retains the explicit Repair / Verify Events Schema Smart Action.
- Schema version is verified and recorded as 1.1.4 only after required objects are confirmed present.

## 1.1.2
- Stabilized Dashboard, Venues, Categories and Settings with defensive data access.
- Added module-owned exception handling so useful errors are visible instead of being swallowed by the Core page wrapper.
- Added Diagnostics page for database driver, schema version, required tables and Registration 2.0 columns.
- Added migration 003 to verify/repair required v1.1 schema columns and record schema version 1.1.2.
- Preserved the approved Events v1.1 admin visual system and Platform 1.1 API/SDK architecture.

# Events Changelog

## 1.1.0 — 2026-08-28
- Rebuilt administration around Developer Platform 1.1 module-owned admin pages and the approved Events dashboard visual language.
- Added Registration 2.0 attendee types, priced options/add-ons, capacities, waitlists and member-only flags.
- Added QR/manual check-in workspace and registration schema fields for signed check-in credentials, confirmation codes and check-in timestamps.
- Added Reports, Attendees, Waitlists, Venues, Settings and API workspaces.
- Added setup wizard, dashboard contribution, search provider, Smart Action, integration listeners and current SDK job registration.
- Added public Event Detail / Registration and Registration Button Builder widgets.
- Event mutations use Core Events / Registration 2.0 endpoints; payments/refunds remain owned by central Finance/Payments integration.
- Removed legacy standalone admin chrome from the primary experience.

## 1.0.0 — 2026-08-14
- Initial Events module baseline.

## 1.1.2
- Schema repair release: install/update now explicitly converges partial Events schemas.
- Creates missing categories, venues, settings, registration fields and registration types tables.
- Adds missing Registration 2.0 columns including registration_mode, amounts, confirmation and QR check-in fields.
- Adds Diagnostics Repair / Verify Events Schema action.
- Clarifies recurring-event generation horizon setting.
Module

Events 1.1.26

development · published · 2026-10-01T22:33:43+00:00

Fixes Events 1.1.25 installation on strict DivisionDesk error handling by removing the redundant global PDO import from the event-scope migration. Preserves Camp Commander/Adjutant scoped event create, edit, publish, archive and delete authorization.

Full package changelog
# 1.1.26 QA

- Fix installation failure caused by `use PDO;` in the global-namespace event-scope migration.
- Preserve 1.1.25 Camp-scoped event authorization and migration behavior.

# Events 1.1.25

- Adds organization scope to events. Existing events converge to Division/default.
- Camp Commander and Camp Adjutant may create, edit, publish/archive, and delete only events owned by their own Camp.
- Camp-scoped authorization is enforced server-side for save, cancel/archive, and delete operations.
- Camp officers see only their Camp events in Events administration; Division event administrators retain Division-wide authority.
- Camp event saves use the module-owned scoped save action instead of the legacy global Core save endpoint.

# Events 1.1.24
- Registration Closes remains a configurable date/time.
- Leaving it blank now explicitly means registration closes when the event begins.
- Existing registration-enabled events with no close time are converged to their event start so Core's server-side registration endpoint rejects late/direct submissions.
- The module editor synchronizes Core and Events registration timing columns after each save.
- Public registration shows a closed/not-yet-open message instead of a form outside the allowed window.
- `Register Now` is not shown after registration closes.
- Verified public Events list/upcoming/featured queries already exclude occurrences once their start time has passed.
- No Core update required.

# Events 1.1.23
- FIX: The blank public `Events` title area is now suppressed using the actual DivisionDesk Builder heading markup (`cms-block--heading`) on event-detail pages.
- The previous 1.1.22 selector looked for a `cms-hero`, which is not what this page uses; therefore it could never hide the title shown in the test screenshot.
- The Events listing page remains unchanged.
- Retains 1.1.22 tab-scroll, registration UI, and Schedule editor toolbar fixes.
- No Core change.

# Events 1.1.22
- FIX: Public tab clicks no longer jump the browser back to the top of the event card; the native tab radio state is fixed to the viewport rather than positioned at the article top.
- FIX: Event-detail pages hide the generic CMS `Events` hero/blank title area. The Events listing page is unchanged.
- FIX: Schedule rich-text toolbar buttons have explicit contrasting backgrounds/text so formatting icons remain visible.
- FIX: `Register & Pay Online` is shown only when the installed Finance module exposes the supported Events checkout contract.
- Paid Events registrations work with Finance 1.2.9+; `Register — Pay Later` remains available independently.
- No Core changes.

# Events 1.1.21
- FIX: Public Overview / Schedule / Location / Registration tabs no longer depend on JavaScript. They use native radio/label state plus CSS, so exactly one panel is selected without a JS tab handler.
- FIX: Register Now switches directly to the Registration panel using that same native mechanism.
- FIX: Corrected an undefined `$eventId` reference in the generated registration JavaScript; the real event ID is now used.
- FIX: Standalone Registration Button widget no longer inherits tab-only hidden styling.
- No Core, Finance, or Membership Manager changes.

# Events 1.1.20
- Removed attendee type selection from the new public registration flow.
- Member number and Camp name/number are available on every registration and are optional except member number on explicitly members-only events.
- Additional Guests is built in and defaults to $0 additional registration fee.
- Event admins may explicitly apply the base registration fee to each additional guest.
- Add-on quantities are independent of primary registrant/guest count.
- Blank add-on quantity means zero.
- Quantity add-ons with per-item choices allow blank choices after a confirmation warning.
- Added a canonical Core rich-text Schedule editor and public Schedule rendering.
- Preserves historical attendee-type data for existing registrations.
- Requires Core 4.6.12+.

# Events 1.1.19

- Public event tabs are now genuinely mutually exclusive. Overview, Schedule, Location and Registration occupy the same content region; inactive panels are both hidden and `display:none`.
- `Register Now` activates the Registration panel instead of appending/scrolling to a second copy of event content.
- Attendee types may be removed from active configuration even when historical registrations reference them; in that case the type is archived and history is preserved.
- An active attendee type named `Guest` automatically creates an `Additional Guests` registration control using that Guest price. Selecting 2 guests creates exactly 2 required guest-name fields.
- Priced Select/Radio options with choices are normalized to `quantity_choice`, so a Banquet priced per person gets a quantity selector and one Beef/Chicken/etc. selector per purchased unit.
- Reducing a guest/option quantity removes excess DOM controls, so hidden stale names/choices are not submitted.
- Requires Core 4.6.11+ because Core owns authoritative server-side quantity normalization and pricing.

# Events 1.1.18
- Registration is now a true event tab instead of content appended below Overview.
- Primary attendee collects full name, address, phone and email; member-only registrations also require member number and Camp name/number.
- Logged-in members auto-fill from the Membership Manager provider when available.
- Adds Guest Names options: selecting quantity N creates exactly N guest-name fields.
- Adds Quantity + per-item choice options: quantity N creates exactly N choice selectors, e.g. Beef/Chicken for each meal.
- Reducing a quantity removes and clears excess guest/choice inputs immediately.
- Quantity pricing updates live and zero quantity means no charge.
- Hides legacy duplicate `Registration Fee` add-ons when attendee type pricing already provides the base registration price.
- Retains 1.1.17 pay-now/pay-later and duplicate-submit fixes.

# Events 1.1.17
- Fixes duplicate registrations caused by Core and Events both submitting the same form.
- Fixes Save/Publish redirecting to legacy Core Events admin.
- Adds Register & Pay Online / Register — Pay Later and a live registration/add-on/total breakdown.
- Finance completion marks the matching registration paid/confirmed.
- My Events matches member ID or email and is moved before the site footer.
- Retains 1.1.16 toggle persistence and 1.1.15 rich public detail restoration.

# Events 1.1.16

- Fixes the Events module editor Registration switch turning itself back off after Save.
- Core `registration_enabled` and Events `registration_mode` are now explicitly synchronized.
- The module's post-save integration action writes both fields, so public registration becomes available immediately after enabling it.
- Event reads treat Core's `registration_enabled` compatibility field as authoritative when an older/stale `registration_mode` disagrees.
- Waitlist state is also carried through the same module extras save.
- All 1.1.15 public detail/card/routing and 1.1.13 registration/check-in/refund functionality is retained.

# Events 1.1.15

- Rebuilt from the untouched Events 1.1.13 package, not from 1.1.14.
- Preserves the 1.1.13 rich registration, QR/check-in, cancellation/refund, My Events, attendee/options and Finance integration code.
- Adds only the missing `days()`, `daysUntil()` and `startingPrice()` helpers required by the existing public detail renderer.
- Upcoming/Next/Featured event cards are styled, clickable and show `Cost: Starting at $xx.xx` for paid events.
- `/events?event=ID` now hands the Events page into the existing full Event Detail / Registration renderer instead of looping to the same list card.
- Adds narrow duplicate-submit protection to the legacy and current event editors.

# Changelog

## 1.1.13

- Fixed the false Core "Check-in code is invalid" toast after a successful short confirmation-code check-in by removing the native form-submit path entirely. The Events check-in control now uses one explicit AJAX action for short codes and only calls Core directly for signed credentials.
- Quick Actions on the Events dashboard is now a working no-JavaScript dropdown with direct links to Check-in, Registrations, Attendees, Reports and Settings.
- Removed the duplicated Core module title/card from Events administration and expanded the Events application shell to the available admin width without modifying Core.
- Expanded My Events management: members can open registration details, add guests through Core Registration 2.0 (including required guest options/add-ons), add available zero-cost options, remove options only when cancellation/refund policy allows, and cancel the full registration when permitted.
- Paid option additions are intentionally blocked before mutation when Core/Finance has no safe incremental-charge contract; the module will not silently add an unpaid charge to an already-paid registration.
- Paid refundable option removal creates an itemized refund request for Finance review instead of silently changing historical payment data.

## 1.1.12
- Audited against DivisionDesk Core 4.4.4 without changing Core.
- Fixed camera flow so permission is requested before decoder capability checks; added native BarcodeDetector + jsQR fallback scanning.
- Check-in now accepts a full QR URL, signed token, or visible confirmation code such as `761A88ED8D`.
- Bypassed the Core subdirectory QR double-prefix issue in the Events public flow by generating a correct module-owned QR from the signed credential.
- Added SDK-based `/my-events` management/cancellation controls for signed-in members.
- Aligned runtime data access with Core Registration 2.0 (`first_name`/`last_name`, `confirmed`/`waitlisted`, `price_cents`, `event_registration_options`, `event_registration_answers`).
- Refund calculations now use Core paid totals and answer price snapshots when available.
- Prevented Events uninstall from dropping Core-owned event/registration tables.

## 1.1.11
- Added attendee self-cancellation using confirmation code + registration email, with per-event cancellation controls and cutoff date.
- Added event-level refund modes plus per-attendee-type and per-option refund policies (inherit/refundable/nonrefundable/manual).
- Paid cancellations create auditable itemized refund requests; Events never moves money directly and leaves actual refund processing to Core/Finance.
- Added optional automatic waitlist promotion when a confirmed registration cancels.
- Reworked confirmation URL normalization so the configured DivisionDesk base path is never prepended twice by Events.
- Expanded schema convergence and Diagnostics for cancellation/refund fields and refund-request storage.
- Documented that the QR image on Core's confirmation/badge page is Core-owned; Events Check-in safely extracts the signed token even if a scanned QR contains a URL.

## 1.1.9
- Prevented duplicate public registration submissions with a single raw same-origin request, submit locking, button disabling, and a short post-success lock.
- Public registration now explicitly renders every active option/add-on and labels each one Required or Optional; only required fields receive browser validation.
- Successful registration stays in the Events registration experience rather than automatically following Core legacy redirects.
- Confirmation URLs returned by Core are normalized to the configured DivisionDesk public base path for subdirectory installs.
- QR check-in accepts a raw signed credential or extracts token/credential/checkin_token/code values from a scanned QR URL.
- Removed the module link to undocumented `/events-badge.php`, which could produce a 404; registrations now link to the supported Check-in workspace.

## 1.1.8
- Removed duplicate Core/page heading presentation from Events module pages and widened the Events workspace.
- Published one-off events are now immediately discoverable by public Events widgets even if an occurrence row has not yet been materialized.
- Added an in-module public event preview so administrators can test the exact public event/registration experience before placing widgets.
- The Registration Button widget now resolves the selected/next published event and exposes a working registration flow instead of an orphan anchor.
- Event presentation fields (summary, featured image, city/state, timezone, all-day/featured flags) are persisted after the frozen Core save contract through an Events Smart Action.
- Public widget queries now fall back safely to base event dates when occurrence materialization is not available.

- Made event options/add-ons truly optional and removed invalid nested forms.
- Added multiple option/type creation controls and remove actions.
- Added cancel/archive and guarded permanent delete event actions.
- Kept successful saves inside the polished Events module editor.
- Expanded responsive layout to a centered wide workspace instead of a cramped Core column.

## 1.1.6
- Full runtime schema convergence for registration types, registration fields, and categories, including active/sort_order and every column referenced by current queries.
- Diagnostics/schema health now verifies those query-critical columns before reporting current.

# Changelog

## 1.1.6
- Fixed Dashboard/Events/Check-in compatibility with Core-created event rows that use `location` rather than `location_name`.
- Added Core 4.3.4 event-contract compatibility fields non-destructively and synchronized legacy display fields.
- Fixed partial output-buffer leakage so a caught page exception no longer duplicates the Events rail/layout.
- Event saves now return to the DivisionDesk Events module editor instead of the legacy Core `/events-admin.php` screen.
- Registration type/option saves stay inside the module UI instead of following Core legacy redirects.
- Removed negative-margin module layout behavior that could collide with the Core admin shell.
- Diagnostics now verifies both Core event-contract fields and Events display fields.

## 1.1.4
- Added request-time schema health checking and idempotent self-healing so Store replacements no longer depend on Install/Update lifecycle hooks.
- Schema repair directly converges missing Events/Registration 2.0 tables and columns without deleting existing event data.
- Diagnostics exposes automatic repair failures and retains the explicit Repair / Verify Events Schema Smart Action.
- Schema version is verified and recorded as 1.1.4 only after required objects are confirmed present.

## 1.1.2
- Stabilized Dashboard, Venues, Categories and Settings with defensive data access.
- Added module-owned exception handling so useful errors are visible instead of being swallowed by the Core page wrapper.
- Added Diagnostics page for database driver, schema version, required tables and Registration 2.0 columns.
- Added migration 003 to verify/repair required v1.1 schema columns and record schema version 1.1.2.
- Preserved the approved Events v1.1 admin visual system and Platform 1.1 API/SDK architecture.

# Events Changelog

## 1.1.0 — 2026-08-28
- Rebuilt administration around Developer Platform 1.1 module-owned admin pages and the approved Events dashboard visual language.
- Added Registration 2.0 attendee types, priced options/add-ons, capacities, waitlists and member-only flags.
- Added QR/manual check-in workspace and registration schema fields for signed check-in credentials, confirmation codes and check-in timestamps.
- Added Reports, Attendees, Waitlists, Venues, Settings and API workspaces.
- Added setup wizard, dashboard contribution, search provider, Smart Action, integration listeners and current SDK job registration.
- Added public Event Detail / Registration and Registration Button Builder widgets.
- Event mutations use Core Events / Registration 2.0 endpoints; payments/refunds remain owned by central Finance/Payments integration.
- Removed legacy standalone admin chrome from the primary experience.

## 1.0.0 — 2026-08-14
- Initial Events module baseline.

## 1.1.2
- Schema repair release: install/update now explicitly converges partial Events schemas.
- Creates missing categories, venues, settings, registration fields and registration types tables.
- Adds missing Registration 2.0 columns including registration_mode, amounts, confirmation and QR check-in fields.
- Adds Diagnostics Repair / Verify Events Schema action.
- Clarifies recurring-event generation horizon setting.
Module

SCV Operations 3.0.20

development · published · 2026-10-01T22:33:38+00:00

Acceptance update: Find a Camp, Division At Large, immediate Finance dues checkout after applicant submission, Finance completion tracking, and graceful public handling of admin-only builder URLs.

Module

Communications 1.4.27

development · published · 2026-09-25T21:57:46+00:00

Adds reusable mailing lists, CSV/manual recipient management, a dynamic All Members audience, multi-list campaign selection, and email deduplication while preserving the existing campaign delivery pipeline.

Full package changelog
## 1.4.26 - 2026-09-25
- Fix Cubicle update lifecycle: add Lifecycle::update() and run schema/endpoints/seeding during module upgrades.

# Communications 1.4.25 QA

- Added Mailing Lists management with manual recipients and CSV import.
- Added dynamic All Members audience representing everyone on the Membership Manager roster with a usable email address.
- Campaigns can combine All Members and multiple custom lists; duplicate email addresses are resolved once.
- Existing newsletter, Camp, role, manual, suppression, unsubscribe, scheduling, recurrence, analytics, and delivery flows remain in place.

# Communications 1.4.24 — Initial chat hydration performance

## 1.4.24
- Removed the unconditional browser GET to `communications-chat.php?after=0&read=0` during initial public-page load.
- Returning visitors with an existing live-chat cookie are hydrated server-side while the page is generated.
- Visitors without an existing chat cookie start with an empty client state and do not call the chat endpoint until chat is opened/used.
- Existing later chat requests, SSE, long-poll fallback, unread handling, and send behavior remain unchanged.

# Communications 1.4.23 — Member-admin alert authentication

- Staff alert badge/count endpoint now accepts Core unified authenticated principals, so a signed-in member with an assigned administrative role is not incorrectly returned 401 merely because they are not using a separate admin-account login. Permission enforcement remains `communications.inbox`.

## 1.4.23
- Newsletter subscriber audiences can target any active Core newsletter list; recipients are resolved at send time so scheduled and recurring campaigns honor current opt-ins/opt-outs.
- Campaigns now excludes `status=system` transactional/module-generated notification records from the user campaign workspace while preserving their deliveries and analytics.
- Added true recurring campaigns: daily, weekly, monthly by day-of-month or ordinal weekday, and yearly schedules with optional start date and end-by-date/end-after-count controls.
- Recurring campaigns create an immutable child run for each occurrence; recipients are resolved when the run is due, each run retains its own delivery history, and the parent campaign rolls email engagement up across runs.
- Added recurring campaign pause/resume/edit/reuse actions and clear next-send/run-count display. A recurrence that fails preflight is automatically paused rather than generating repeated failed runs every scheduler pass.
- Improved Campaigns visual hierarchy with consistent inline SVG navigation/channel/action icons, compact icon actions, schedule badges, and clearer scheduled/recurring filtering.
- Added send-time `{{communications.upcoming_events}}` dynamic content. The composer has a calendar insert control; published future Core Events are rendered when the email actually sends, so recurring event digests stay current without rebuilding the campaign.
- Campaign performance now exposes per-occurrence run history for recurring campaigns while retaining parent-level rolled-up open/click analytics. Added explicit End recurrence alongside Pause/Resume.

## 1.4.20
- Added Reuse for every saved campaign. Reuse copies campaign content, audience, channels and topic into a new unsaved campaign while deliberately excluding delivery history, analytics, status, approval and schedule.
- Added Edit for draft, scheduled and pending-approval campaigns; sent/queued history remains immutable.
- Reuse/Edit are permission-gated by `communications.compose`.

## 1.4.18 — 2026-09-09
- Redesigned Communications navigation with a dedicated module sidebar for faster access to Campaigns, Inbox, Templates, Deliverability, Providers, Live Chat, Staff Alerts and Status.
- Reorganized the Campaigns screen around a dashboard-first workflow: summary cards and campaign history appear first; **New Campaign** opens the composer only when needed.
- Added campaign status tabs and live search without changing campaign persistence, delivery, scheduling or approval behavior.
- Added per-campaign email engagement summaries directly in Campaigns: unique opens, total opens, open rate, unique clicks, total clicks and click rate.
- Added a campaign performance modal with deliveries, email deliveries, failures and engagement metrics.
- Campaign engagement reads the existing Communications tracking data that already feeds Core Analytics; no second tracking pipeline was introduced. Unique counts remain first-observed-per-delivery, while total counts include repeat tracking observations.
- Preserves all 1.4.17 delivery, transactional attachment, open/click tracking and Analytics event behavior.

## 1.4.17 — 2026-09-08
- Preserves existing first/unique `communications.email.opened` and `communications.email.clicked` analytics events.
- Records every valid tracking request as `communications.email.open_observed` / `communications.email.click_observed` so repeat engagement can be reported without inflating unique open/click rates.
- Provider tracking events are recorded on every valid request for short-term diagnostics; normalized Core Analytics remains the long-term reporting store.
- Adds a read-only email campaign/delivery directory method used by Core Analytics for campaign and recipient labels.
- Retains 1.4.16 attachment-capable transactional email delivery unchanged.

## 1.4.14 — 2026-09-04
- Added **Send Now (Don’t Save)** for one-off broadcasts that should be delivered and tracked without creating a saved campaign record.
- Added Delete actions for old campaigns. Completed delivery history is retained for analytics while pending delivery work is cancelled safely.
- **Save & Send Now** and draft **Send** now start a small immediate delivery batch in the web request instead of waiting entirely on the next scheduler interval; larger sends continue through Core's durable queue.
- Added a 60-second Communications queue-recovery job that recreates missing durable Core jobs for queued deliveries.
- Retains automatic parent campaign completion, open/click tracking, and the canonical tracked **Visit our website** footer link.
- Campaign actions update the Campaigns panel over AJAX without requiring a page refresh.

## 1.4.13
- Reworked the campaign composer around a clear normal workflow: Save Draft, Save & Schedule, or Save & Send Now.
- Moved Email Test, Preflight Analysis, and Full Deliverability Test into an optional Testing & Deliverability section so test utilities no longer look like the primary send workflow.
- Added in-place campaign-list refresh after save/schedule/send so newly saved campaigns appear immediately without a browser refresh.
- A saved draft now keeps its campaign ID in the composer; subsequent saves update that draft instead of inserting another campaign. A server-side submission token also makes duplicate AJAX/form submissions idempotent, preventing two rows even if the submit handler fires twice.
- Added a New Campaign action to deliberately clear the current saved draft and begin another campaign.
- Save & Send Now persists and queues the campaign in one action; Save & Schedule requires an explicit scheduled date/time. Approval-required campaigns are saved into the approval workflow rather than sent directly.

## 1.4.12
- Campaign status now advances from `queued` to `sent` after all deliveries complete, or `failed` after terminal delivery failure, instead of remaining permanently queued.
- Every tracked HTML email now receives a canonical `Visit our website` link immediately beside the open-tracking pixel; the link is routed through Communications click tracking.

## 1.4.11 — 2026-09-04

### Fixed
- Campaign test emails now create a Communications delivery record before MIME generation and receive the same signed per-delivery 1×1 open pixel and tracked links as bulk campaign deliveries.
- Bulk campaign tracking decoration now happens after the unsubscribe/footer HTML is assembled, so the final HTML MIME body contains the tracking pixel.
- `Tracking::decorateHtml()` now independently honors open-tracking and link-tracking flags instead of applying both whenever either was enabled.
- Test-send success/failure is recorded through Communications delivery/analytics events so real SMTP test messages can verify send → open → click behavior.

### Improved
- Campaign composer wording now clearly exposes `All active Membership Manager members in my scope` as the full scoped bulk-email audience and explains Camp, role, and manual targeting.

# Communications 1.4.10

- Preserves signed 1x1 open-pixel analytics for Communications email delivery.
- Adds independent open-pixel and link-tracking controls (`disable_open_tracking`, `disable_link_tracking`) while preserving `disable_tracking` as the master opt-out.
- Keeps first-open/first-click Analytics recording behavior unchanged.
- Core-owned email paths that bypass Communications still require the Core transactional-mail bridge and are not intercepted by this module alone.

# DivisionDesk Communications 1.4.9

- Added site-specific branding to every browser push notification.
- Push titles now include the configured Core site name rather than generic DivisionDesk branding.
- Uses the site's configured logo as the notification icon and favicon/logo as the badge when available.
- Preserves module-supplied images, icons, badges, and actions instead of overwriting them.
- Adds a default `Open` notification action when a destination URL exists and the browser/OS supports actions.
- Improved service-worker click handling for relative and subdirectory URLs.
- Retains all 1.4.2–1.4.8 concurrency, Campaigns, service-worker, VAPID, encryption, delivery, and URL-prefix fixes.

# DivisionDesk Communications 1.4.8

- Fixed browser-push links receiving the DivisionDesk installation prefix twice.
- Central push URL normalization is now idempotent: URLs already beginning with Core `basePath()` are preserved.
- Social Media alert URLs are no longer pre-expanded before the centralized normalization step.
- Retains all 1.4.2–1.4.7 performance, Campaigns, service-worker, VAPID, encryption, and push-delivery fixes.

# DivisionDesk Communications 1.4.7

- Fixed browser-push links dropping the DivisionDesk installation prefix on subdirectory sites.
- Centralized site-local push URL normalization through Core `Url::to()`.
- Social Media push alerts now explicitly normalize their inbox destination before delivery.
- Staff alert fallback links are also normalized through Core URL handling.
- Fully-qualified external URLs and special schemes remain unchanged.
- Retains all 1.4.2–1.4.6 performance, Campaigns, service-worker, VAPID, and Web Push delivery fixes.

# DivisionDesk Communications 1.4.6

- Fixed Web Push deliveries failing with `Undefined array key "urgency"` when a notification omitted an explicit urgency value.
- Social Media push alerts now explicitly use `urgency=normal` and a 24-hour TTL.
- Normalized ephemeral P-256 X/Y coordinates to exactly 32 bytes before Web Push payload encryption.
- Retains the 1.4.5 VAPID-key fix, 1.4.4 base-path service-worker fix, 1.4.3 Campaigns JS fix, and 1.4.2 concurrency fixes.

# DivisionDesk Communications 1.4.5

- Fixed Web Push enrollment failures caused by invalid-length VAPID P-256 keys.
- Generated EC X/Y coordinates and private scalar are now left-padded to exactly 32 bytes before base64url encoding.
- Push subscription discovery now validates the stored VAPID public key and returns a precise setup error if it is invalid.
- Retains the 1.4.4 service-worker base-path fix, 1.4.3 Campaigns JS fix, and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.4

- Fixed Web Push service-worker registration on installations hosted below the domain root.
- Push subscription discovery now uses Core `Url::to()` so the service worker resolves inside the active DivisionDesk installation, e.g. `/new_test_site/public/divisiondesk-push-sw.js`.
- Retains the 1.4.3 Campaigns JavaScript rendering fix and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.3

- Fixed raw JavaScript appearing as visible text at the bottom of the Campaigns screen.
- Moved Campaigns UI JavaScript from a large inline heredoc to `communications-campaigns.js`.
- Public endpoint setup now deploys and validates that asset automatically.
- Retains Communications 1.4.2 lightweight polling/session-lock fixes.

# DivisionDesk Communications 1.4.2

- Generated high-frequency alert-count, chat, and inbox API endpoints now use Core lightweight bootstrap.
- These endpoints release the PHP session immediately and skip unrelated full add-on boot work, preventing long-poll/chat traffic from blocking normal admin pages.
- Works with Core 4.6.8 single-flight alert polling to prevent request pile-ups on shared hosting.

# Changelog

## 1.4.1
- Added normalized Core Analytics events for campaign queueing, notification queueing, delivery sent/delivered/failed/suppressed, email sent/opened/clicked/failed, live-chat start/inbound messages, and staff replies/internal notes.
- Email-open Analytics is explicitly low-confidence and click Analytics medium-confidence; member/campaign context is included when available.
- Added a Social Media alert event bridge: when Social push notifications are enabled, new external social comments/messages/mentions are pushed immediately to active admin Web Push subscriptions.
- Social push delivery does not create duplicate onsite alerts; Social Media remains the canonical global alert provider.

# Communications Changelog

## 1.4.0
- Replaced fixed chat polling with SSE-first transport and automatic long-poll/short-poll fallback for shared hosting.
- Added signed 1x1 email open tracking and safe HTTP(S) click tracking for Communications deliveries.
- Email opens/clicks now update delivery timestamps and Core Analytics signals.
- Preserved unread chat state when the widget is closed.

# DivisionDesk Communications Changelog

## 1.3.0 — 2026-08-15
### DivisionDesk notification-center integration
- Unread Communications staff alerts appear in the main DivisionDesk Administration notification bell.
- The bell is hidden when there are no unread alerts.
- Clicking a Communications alert marks that alert read and opens the exact related conversation.
- Communications registers its Web Push enrollment with Core so administrators are prompted at the top of Administration when browser notifications are available but not enabled on the current device.
- Existing Inbox unread badges, email alerts, push alerts and optional SMS staff alerts remain available.

## 1.2.5 — 2026-08-15
### Messaging usability
- Fixed the admin Inbox so long conversations scroll inside the message pane instead of expanding the whole page.
- Conversation list and current thread now own independent scroll regions.
- Reply composer remains anchored at the bottom of the current conversation.
- Mobile Inbox keeps a bounded scrollable conversation list and a dedicated thread viewport.
- Replaced the very short single-tone notification beep with a softer, longer two-tone chat chime.
- The improved notification sound is used consistently for new messages on both the staff Inbox and visitor chat.

## 1.2.4 — 2026-08-15
### Live messaging workflow
- Live chat requires the visitor's name and email address.
- A staff chat reply that remains unread for two minutes is emailed to the visitor; active visitors who read it in chat do not receive a duplicate email.
- Visitor name is now required before starting live chat so staff can distinguish conversations.
- Visitor chat persists across public-page navigation; an open chat reopens on the next page, while an intentionally closed chat remains closed.
- Visitor chat polls automatically and plays a short sound when a genuinely new staff reply arrives.
- Communications Inbox is now a two-pane live messaging workspace with all conversations visible beside the current thread.
- Conversation list and current thread refresh automatically without page reload.
- Admin receives a short sound when a genuinely new inbound message arrives.
- Replies, internal notes, status changes, assignments and conversation switching are fetch-driven.
- Conversation list shows visitor name, latest-message preview, channel, status and unread count.
- Open/pending, all, and resolved conversation views are available without overwhelming the default screen.

## 1.2.3 — 2026-08-15
### Staff message alerts
- New live chat, website-form and inbound SMS messages can notify staff automatically.
- Communications Inbox shows a live unread badge in DivisionDesk administration.
- On-site staff alerts link directly to the conversation.
- Email alerts are sent for new conversations by default; Advanced can email every inbound message.
- Browser push can be enabled independently on each staff device.
- Optional SMS alerts can be sent to configured staff numbers.
- Opening a conversation marks its associated staff alerts read.
- Staff Alerts settings save with fetch and include plain-language readiness/help.

## 1.2.2 — 2026-08-15
### Critical fix
- `communications-chat.php` and all other generated Communications public endpoints are now ensured whenever the module registers.
- Upgraded installations self-heal if an earlier update did not regenerate public endpoints.
- Removed suppressed writes from endpoint generation.
- Endpoint generation now fails loudly when `public/` is unavailable/unwritable or a generated file cannot be written.
- Final required-file verification runs before endpoint generation returns success.
- Existing generated files are rewritten only when contents differ.

### Regression tests
- Fresh endpoint generation.
- Upgrade simulation beginning from the pre-chat endpoint set.
- Missing-chat self-healing.
- Idempotent regeneration.
- Failure-path test proving an invalid public path no longer silently succeeds.

## 1.2.1 — 2026-08-15
### Critical upgrade fix
- Replaced the old single-table `Schema::ensure()` shortcut with a sequential migration ledger.
- Existing Communications installations now run every missing migration in natural version order instead of returning early when the original templates table already exists.
- Live-chat migration `003_live_chat.php` therefore runs correctly during module update, not only on fresh installs.
- Migration failures are transactional where supported and identify the exact migration that failed.
- Schema completion is checked after migrations.

### Packaging
- `addon.json` and `manifest.json` explicitly declare `package_type: module`.
- Version bumped to 1.2.1 so it cannot collide with the rejected/staged 1.2.0 package history.

## 1.2.0 — 2026-08-15
### Completed
- Site-wide live chat is automatically injected on public pages when Communications is enabled; no floating widget placement is required.
- Chat uses a speech-bubble icon, fetch-driven history/send/poll, secure guest session cookie, unread badge, mobile full-screen UI, office hours/away message, identity requirements, optional avatar/accent and path exclusions.
- Chat conversations and staff replies are fully integrated with the Communications Inbox.
- Contact/Message widget now provides Contact Card and fetch-driven Inline Form layouts; obsolete Floating Button layout removed.
- SMS provider validation now includes stored secrets; Providers includes real SMS test, segment count and administrator-configured approximate cost.
- Web Push VAPID key generation is exposed when the required runtime library is available.
- Reports include normalized provider callback outcomes.
- System Status page explicitly reports operational, configuration-required, dependency-required, disabled and unsupported-external-workflow states.

### Compatibility
- Requires DivisionDesk Core 3.6.4 for automatic public-page integration.
- Coordinated DivisionDesk Server 1.11.4 adds bounded independent DKIM verification and DMARC evaluation via aligned DKIM.

## 1.1.4 — 2026-08-14
### Fixed
- Full Deliverability create/status calls allow up to 20 seconds for bounded DivisionDesk Server analysis.
- Rebuilt directly from the publisher-validated Communications 1.1.2 package to eliminate staging ambiguity from the rejected 1.1.3 package.

## 1.1.2 — 2026-08-14
### Improved
- Deliverability modal now displays **Test Coverage** separately from Inbox Probability.
- Unavailable SpamAssassin and reputation checks are shown as `Not checked`/`Unable to check` rather than visually implying failure.
- Authentication shows evidence-aware states: Pass, Fail, Signature Present, Policy Present, or Unknown.
- Content & Links now includes a detailed reputation-query report showing provider, tested IP/domain, DNS response, interpretation and query.
- Reputation results distinguish **Clear**, **Listed**, and **Unable to Check**.
- Recommendations explain excluded/unavailable signals instead of treating them as negative delivery evidence.

## 1.1.1 — 2026-08-14
### Fixed
- Deliverability results now render as a true fixed overlay instead of appearing at the bottom of the Campaigns page.
- Mobile view becomes a full-screen sheet with scrollable details.
- Page scrolling is locked while the modal is open.
- Restored the `TestEmail::send(..., $options)` signature needed to attach the secure live-test correlation header.
- Live status displays mailbox-poll warnings instead of silently waiting forever.

## 1.1.0 — 2026-08-14
### Added
- Instant campaign Preflight Analysis.
- Full Deliverability Test through `mailtest@divisiondesk.com`.
- Secure DivisionDesk Server create/status test workflow.
- Actual campaign is sent through the site's configured SMTP transport with a correlation header.
- Responsive circular Inbox Probability gauge with gradual deep-red → red → orange → yellow → green progression.
- Large desktop modal becomes a full-screen mobile sheet.
- Live polling states: sending, waiting, received/analyzing, complete.
- SpamAssassin, authentication, blocklist, structure, content/link and recommendations tabs.
- Fetch-driven workflow; Campaign composer never reloads during testing.

### Changed
- Inbox Probability is explicitly presented as a DivisionDesk estimate, not a receiving-provider guarantee.

## 1.0.7 — 2026-08-14

### Fixed
- Fixed Campaign fetch actions returning Administration HTML before JSON.
- AJAX Campaign requests now authenticate/authorize without rendering `AdminUi::start()` first.
- CSRF verification is handled inside the JSON request error path.
- AJAX responses are explicitly JSON and `Cache-Control: no-store`.

### Diagnostics
- If a future fetch request receives non-JSON content, DivisionDesk shows a short excerpt of the actual HTTP response instead of directing the administrator to a server log that may contain no error.

## 1.0.6 — 2026-08-14

### Fixed
- Fixed `SMTP host and a valid envelope/From email are required` when Core has a valid From address but the optional envelope sender is blank.
- Empty `envelope_from` now correctly falls back to Core `from_email`.

### Changed
- Campaign **Send Email Test** and **Save Campaign** now use `fetch()` and display success/errors in place.
- Transport/validation errors no longer refresh the Campaigns page or clear the composer.
- Non-AJAX fallback restores posted campaign fields after a server-rendered error.
- Submit buttons show a busy state and duplicate submissions are prevented.

### UX direction
- Fetch/AJAX-style in-place actions are the preferred DivisionDesk interaction model where practical.
- User-entered form data should survive errors rather than returning to blank forms.

## 1.0.5 — 2026-08-14

### Fixed
- Fixed campaign test failure `List-Unsubscribe must be HTTPS or mailto.`
- Core relative/base-path URLs are no longer inserted directly into email headers.
- HTTPS web requests automatically establish a canonical DivisionDesk public site URL for Communications.
- Background campaign jobs reuse the stored canonical HTTPS site URL.
- Local/LAN/non-HTTPS installations fall back to a standards-valid `mailto:` List-Unsubscribe target instead of emitting an invalid relative URL.
- `List-Unsubscribe-Post: List-Unsubscribe=One-Click` remains limited to actual HTTPS unsubscribe endpoints.
- Avoids duplicating the Core base path when building absolute unsubscribe URLs.

### Diagnostics
- Communications Providers and Deliverability now show whether bulk email is using HTTPS one-click unsubscribe or the mailto fallback.

## 1.0.4 — 2026-08-14

### Fixed
- Communications now reads the existing DivisionDesk Core **Email Delivery** configuration for SMTP and From settings.
- Campaign Email Test no longer incorrectly reports SMTP as unconfigured when Core SMTP is already working.
- SMTP password is consumed from Core Mailer configuration; Communications no longer expects a duplicate `communications.smtp.password`.
- Blank EHLO/HELO remains blank in configuration and is resolved automatically by the mail transport at connection time.
- Campaign and queued email failures now identify the specific missing Core Email Delivery setting.

### Changed
- Communications → Providers no longer presents a second SMTP configuration form.
- The Providers page shows Core email readiness/status and links directly to the global Email Delivery page.
- Communications-owned provider settings are now limited to SMS and Web Push.

## 1.0.3 — 2026-08-14

### Fixed
- Fixed Campaigns buttons appearing to do nothing with Chrome error `An invalid form control with name='push_url' is not focusable`.
- Push URL, image, icon and badge fields now accept DivisionDesk template variables such as `{{site.url}}` without HTML5 URL validation blocking form submission.
- **Send Email Test** now uses `formnovalidate` so hidden/unrelated campaign channel fields cannot prevent a transport/template test from reaching PHP.

## 1.0.2 — 2026-08-14

### Fixed
- Built-in templates now self-heal if a previous installation or upgrade left `communications_templates` empty.
- Added upgrade migration 002 so 1.0.2 reliably invokes the idempotent template seeder after upgrading.
- Module registration, Campaigns, and Templates defensively restore missing built-ins without overwriting existing customized templates.
- Corrected Campaign list column rendering for topic, channels, schedule, deliveries and actions.

### Added
- Rebuilt Campaigns as a polished multi-channel composer.
- Template selection now immediately loads the template subject, styled HTML, plain-text version, SMS text and push payload into the composer.
- Rich HTML email editor with formatting controls and HTML-source toggle.
- Sandboxed email preview and push-notification preview.
- Immediate single-recipient SMTP campaign test using the production Communications email builder, including multipart HTML/text, Date, Message-ID, List-Unsubscribe and one-click unsubscribe headers.
- Improved channel cards/tabs, SMS character count, audience/timing controls and contextual deliverability guidance.
- Redesigned Template Library with cards, statistics, editor, and Restore Missing Built-ins control.
- Upgraded built-in Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Events, Dues Renewal, Welcome, Login Code, Application Status and Contact Response templates with polished inline email styling.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer; Core 3.6.1 is recommended.

## 1.0.1 — 2026-08-14

### Fixed
- Fixed fresh installation failure: `SQLSTATE[HY000]: General error: 1 no such table: communications_templates`.
- Communications now ensures its schema exists before seeding built-in templates.
- Install, enable and update entry points are safe against a partially completed 1.0.0 installation.
- Existing `CREATE TABLE IF NOT EXISTS` migration statements make recovery non-destructive.

### Compatibility
- Works with DivisionDesk Core 3.6.0 and newer.
- Core 3.6.1 separately corrects the generic module lifecycle ordering for all modules.

## 1.0.0 — 2026-08-14

### Added
- Multi-channel campaign model for Email, SMS, Push and on-site delivery.
- Membership Manager audience adapter with active-member, Camp and role targeting.
- Shared background delivery jobs using DivisionDesk Core 3.6 Job Queue.
- Multipart HTML/plain-text email construction with Date, Message-ID, Reply-To, List-ID, List-Unsubscribe and one-click unsubscribe headers where appropriate.
- Non-transactional email footer with physical/site address and unsubscribe link.
- Email header-injection safeguards.
- Deliverability Center with SMTP, sender, SPF and DMARC checks plus DKIM guidance.
- Suppression system for opt-outs, provider failures and invalid destinations.
- Built-in communication templates: Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Event Announcement, Event Reminder, Registration Confirmation, Dues Renewal, Welcome, Login Code, Application Status and Contact Response.
- SMS provider abstraction with Twilio, Amazon SNS and Telnyx outbound adapters.
- Normalized Twilio errors for invalid, landline/non-SMS, unreachable and opted-out numbers.
- Automatic permanent SMS suppression for selected permanent provider failures.
- STOP/START handling for inbound SMS.
- Incoming SMS webhook/conversation handling for Twilio and Telnyx.
- Standards-oriented Web Push subscription database and service worker.
- VAPID Web Push adapter integration point.
- Rich push payload model: title, body, URL, image, icon, badge, actions, tag, TTL, urgency and require-interaction.
- Unified Conversations Inbox for website/contact/SMS messages.
- Public Contact Us / Website Messaging system.
- Member Communication Preferences page.
- Contact, Announcement and Communication Preferences widgets.
- NotificationService API for other DivisionDesk modules to queue transactional or bulk notifications.
- Notification Rule trigger/action foundation.
- Provider settings using Core encrypted Secret Vault.
- Delivery reports, provider-event history and configurable retention foundation.

### Security
- Provider secrets are encrypted by Core 3.6 Secret Vault.
- Twilio webhook signatures are validated before incoming events are trusted.
- Telnyx Ed25519 webhook verification is supported when a public verification key is configured.
- Email header values reject CR/LF injection.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer.
Module

Communications 1.4.25

development · published · 2026-09-25T21:48:39+00:00

Adds reusable mailing lists, CSV/manual recipient management, a dynamic All Members audience, multi-list campaign selection, and email deduplication while preserving the existing campaign delivery pipeline.

Full package changelog
# Communications 1.4.25 QA

- Added Mailing Lists management with manual recipients and CSV import.
- Added dynamic All Members audience representing everyone on the Membership Manager roster with a usable email address.
- Campaigns can combine All Members and multiple custom lists; duplicate email addresses are resolved once.
- Existing newsletter, Camp, role, manual, suppression, unsubscribe, scheduling, recurrence, analytics, and delivery flows remain in place.

# Communications 1.4.24 — Initial chat hydration performance

## 1.4.24
- Removed the unconditional browser GET to `communications-chat.php?after=0&read=0` during initial public-page load.
- Returning visitors with an existing live-chat cookie are hydrated server-side while the page is generated.
- Visitors without an existing chat cookie start with an empty client state and do not call the chat endpoint until chat is opened/used.
- Existing later chat requests, SSE, long-poll fallback, unread handling, and send behavior remain unchanged.

# Communications 1.4.23 — Member-admin alert authentication

- Staff alert badge/count endpoint now accepts Core unified authenticated principals, so a signed-in member with an assigned administrative role is not incorrectly returned 401 merely because they are not using a separate admin-account login. Permission enforcement remains `communications.inbox`.

## 1.4.23
- Newsletter subscriber audiences can target any active Core newsletter list; recipients are resolved at send time so scheduled and recurring campaigns honor current opt-ins/opt-outs.
- Campaigns now excludes `status=system` transactional/module-generated notification records from the user campaign workspace while preserving their deliveries and analytics.
- Added true recurring campaigns: daily, weekly, monthly by day-of-month or ordinal weekday, and yearly schedules with optional start date and end-by-date/end-after-count controls.
- Recurring campaigns create an immutable child run for each occurrence; recipients are resolved when the run is due, each run retains its own delivery history, and the parent campaign rolls email engagement up across runs.
- Added recurring campaign pause/resume/edit/reuse actions and clear next-send/run-count display. A recurrence that fails preflight is automatically paused rather than generating repeated failed runs every scheduler pass.
- Improved Campaigns visual hierarchy with consistent inline SVG navigation/channel/action icons, compact icon actions, schedule badges, and clearer scheduled/recurring filtering.
- Added send-time `{{communications.upcoming_events}}` dynamic content. The composer has a calendar insert control; published future Core Events are rendered when the email actually sends, so recurring event digests stay current without rebuilding the campaign.
- Campaign performance now exposes per-occurrence run history for recurring campaigns while retaining parent-level rolled-up open/click analytics. Added explicit End recurrence alongside Pause/Resume.

## 1.4.20
- Added Reuse for every saved campaign. Reuse copies campaign content, audience, channels and topic into a new unsaved campaign while deliberately excluding delivery history, analytics, status, approval and schedule.
- Added Edit for draft, scheduled and pending-approval campaigns; sent/queued history remains immutable.
- Reuse/Edit are permission-gated by `communications.compose`.

## 1.4.18 — 2026-09-09
- Redesigned Communications navigation with a dedicated module sidebar for faster access to Campaigns, Inbox, Templates, Deliverability, Providers, Live Chat, Staff Alerts and Status.
- Reorganized the Campaigns screen around a dashboard-first workflow: summary cards and campaign history appear first; **New Campaign** opens the composer only when needed.
- Added campaign status tabs and live search without changing campaign persistence, delivery, scheduling or approval behavior.
- Added per-campaign email engagement summaries directly in Campaigns: unique opens, total opens, open rate, unique clicks, total clicks and click rate.
- Added a campaign performance modal with deliveries, email deliveries, failures and engagement metrics.
- Campaign engagement reads the existing Communications tracking data that already feeds Core Analytics; no second tracking pipeline was introduced. Unique counts remain first-observed-per-delivery, while total counts include repeat tracking observations.
- Preserves all 1.4.17 delivery, transactional attachment, open/click tracking and Analytics event behavior.

## 1.4.17 — 2026-09-08
- Preserves existing first/unique `communications.email.opened` and `communications.email.clicked` analytics events.
- Records every valid tracking request as `communications.email.open_observed` / `communications.email.click_observed` so repeat engagement can be reported without inflating unique open/click rates.
- Provider tracking events are recorded on every valid request for short-term diagnostics; normalized Core Analytics remains the long-term reporting store.
- Adds a read-only email campaign/delivery directory method used by Core Analytics for campaign and recipient labels.
- Retains 1.4.16 attachment-capable transactional email delivery unchanged.

## 1.4.14 — 2026-09-04
- Added **Send Now (Don’t Save)** for one-off broadcasts that should be delivered and tracked without creating a saved campaign record.
- Added Delete actions for old campaigns. Completed delivery history is retained for analytics while pending delivery work is cancelled safely.
- **Save & Send Now** and draft **Send** now start a small immediate delivery batch in the web request instead of waiting entirely on the next scheduler interval; larger sends continue through Core's durable queue.
- Added a 60-second Communications queue-recovery job that recreates missing durable Core jobs for queued deliveries.
- Retains automatic parent campaign completion, open/click tracking, and the canonical tracked **Visit our website** footer link.
- Campaign actions update the Campaigns panel over AJAX without requiring a page refresh.

## 1.4.13
- Reworked the campaign composer around a clear normal workflow: Save Draft, Save & Schedule, or Save & Send Now.
- Moved Email Test, Preflight Analysis, and Full Deliverability Test into an optional Testing & Deliverability section so test utilities no longer look like the primary send workflow.
- Added in-place campaign-list refresh after save/schedule/send so newly saved campaigns appear immediately without a browser refresh.
- A saved draft now keeps its campaign ID in the composer; subsequent saves update that draft instead of inserting another campaign. A server-side submission token also makes duplicate AJAX/form submissions idempotent, preventing two rows even if the submit handler fires twice.
- Added a New Campaign action to deliberately clear the current saved draft and begin another campaign.
- Save & Send Now persists and queues the campaign in one action; Save & Schedule requires an explicit scheduled date/time. Approval-required campaigns are saved into the approval workflow rather than sent directly.

## 1.4.12
- Campaign status now advances from `queued` to `sent` after all deliveries complete, or `failed` after terminal delivery failure, instead of remaining permanently queued.
- Every tracked HTML email now receives a canonical `Visit our website` link immediately beside the open-tracking pixel; the link is routed through Communications click tracking.

## 1.4.11 — 2026-09-04

### Fixed
- Campaign test emails now create a Communications delivery record before MIME generation and receive the same signed per-delivery 1×1 open pixel and tracked links as bulk campaign deliveries.
- Bulk campaign tracking decoration now happens after the unsubscribe/footer HTML is assembled, so the final HTML MIME body contains the tracking pixel.
- `Tracking::decorateHtml()` now independently honors open-tracking and link-tracking flags instead of applying both whenever either was enabled.
- Test-send success/failure is recorded through Communications delivery/analytics events so real SMTP test messages can verify send → open → click behavior.

### Improved
- Campaign composer wording now clearly exposes `All active Membership Manager members in my scope` as the full scoped bulk-email audience and explains Camp, role, and manual targeting.

# Communications 1.4.10

- Preserves signed 1x1 open-pixel analytics for Communications email delivery.
- Adds independent open-pixel and link-tracking controls (`disable_open_tracking`, `disable_link_tracking`) while preserving `disable_tracking` as the master opt-out.
- Keeps first-open/first-click Analytics recording behavior unchanged.
- Core-owned email paths that bypass Communications still require the Core transactional-mail bridge and are not intercepted by this module alone.

# DivisionDesk Communications 1.4.9

- Added site-specific branding to every browser push notification.
- Push titles now include the configured Core site name rather than generic DivisionDesk branding.
- Uses the site's configured logo as the notification icon and favicon/logo as the badge when available.
- Preserves module-supplied images, icons, badges, and actions instead of overwriting them.
- Adds a default `Open` notification action when a destination URL exists and the browser/OS supports actions.
- Improved service-worker click handling for relative and subdirectory URLs.
- Retains all 1.4.2–1.4.8 concurrency, Campaigns, service-worker, VAPID, encryption, delivery, and URL-prefix fixes.

# DivisionDesk Communications 1.4.8

- Fixed browser-push links receiving the DivisionDesk installation prefix twice.
- Central push URL normalization is now idempotent: URLs already beginning with Core `basePath()` are preserved.
- Social Media alert URLs are no longer pre-expanded before the centralized normalization step.
- Retains all 1.4.2–1.4.7 performance, Campaigns, service-worker, VAPID, encryption, and push-delivery fixes.

# DivisionDesk Communications 1.4.7

- Fixed browser-push links dropping the DivisionDesk installation prefix on subdirectory sites.
- Centralized site-local push URL normalization through Core `Url::to()`.
- Social Media push alerts now explicitly normalize their inbox destination before delivery.
- Staff alert fallback links are also normalized through Core URL handling.
- Fully-qualified external URLs and special schemes remain unchanged.
- Retains all 1.4.2–1.4.6 performance, Campaigns, service-worker, VAPID, and Web Push delivery fixes.

# DivisionDesk Communications 1.4.6

- Fixed Web Push deliveries failing with `Undefined array key "urgency"` when a notification omitted an explicit urgency value.
- Social Media push alerts now explicitly use `urgency=normal` and a 24-hour TTL.
- Normalized ephemeral P-256 X/Y coordinates to exactly 32 bytes before Web Push payload encryption.
- Retains the 1.4.5 VAPID-key fix, 1.4.4 base-path service-worker fix, 1.4.3 Campaigns JS fix, and 1.4.2 concurrency fixes.

# DivisionDesk Communications 1.4.5

- Fixed Web Push enrollment failures caused by invalid-length VAPID P-256 keys.
- Generated EC X/Y coordinates and private scalar are now left-padded to exactly 32 bytes before base64url encoding.
- Push subscription discovery now validates the stored VAPID public key and returns a precise setup error if it is invalid.
- Retains the 1.4.4 service-worker base-path fix, 1.4.3 Campaigns JS fix, and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.4

- Fixed Web Push service-worker registration on installations hosted below the domain root.
- Push subscription discovery now uses Core `Url::to()` so the service worker resolves inside the active DivisionDesk installation, e.g. `/new_test_site/public/divisiondesk-push-sw.js`.
- Retains the 1.4.3 Campaigns JavaScript rendering fix and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.3

- Fixed raw JavaScript appearing as visible text at the bottom of the Campaigns screen.
- Moved Campaigns UI JavaScript from a large inline heredoc to `communications-campaigns.js`.
- Public endpoint setup now deploys and validates that asset automatically.
- Retains Communications 1.4.2 lightweight polling/session-lock fixes.

# DivisionDesk Communications 1.4.2

- Generated high-frequency alert-count, chat, and inbox API endpoints now use Core lightweight bootstrap.
- These endpoints release the PHP session immediately and skip unrelated full add-on boot work, preventing long-poll/chat traffic from blocking normal admin pages.
- Works with Core 4.6.8 single-flight alert polling to prevent request pile-ups on shared hosting.

# Changelog

## 1.4.1
- Added normalized Core Analytics events for campaign queueing, notification queueing, delivery sent/delivered/failed/suppressed, email sent/opened/clicked/failed, live-chat start/inbound messages, and staff replies/internal notes.
- Email-open Analytics is explicitly low-confidence and click Analytics medium-confidence; member/campaign context is included when available.
- Added a Social Media alert event bridge: when Social push notifications are enabled, new external social comments/messages/mentions are pushed immediately to active admin Web Push subscriptions.
- Social push delivery does not create duplicate onsite alerts; Social Media remains the canonical global alert provider.

# Communications Changelog

## 1.4.0
- Replaced fixed chat polling with SSE-first transport and automatic long-poll/short-poll fallback for shared hosting.
- Added signed 1x1 email open tracking and safe HTTP(S) click tracking for Communications deliveries.
- Email opens/clicks now update delivery timestamps and Core Analytics signals.
- Preserved unread chat state when the widget is closed.

# DivisionDesk Communications Changelog

## 1.3.0 — 2026-08-15
### DivisionDesk notification-center integration
- Unread Communications staff alerts appear in the main DivisionDesk Administration notification bell.
- The bell is hidden when there are no unread alerts.
- Clicking a Communications alert marks that alert read and opens the exact related conversation.
- Communications registers its Web Push enrollment with Core so administrators are prompted at the top of Administration when browser notifications are available but not enabled on the current device.
- Existing Inbox unread badges, email alerts, push alerts and optional SMS staff alerts remain available.

## 1.2.5 — 2026-08-15
### Messaging usability
- Fixed the admin Inbox so long conversations scroll inside the message pane instead of expanding the whole page.
- Conversation list and current thread now own independent scroll regions.
- Reply composer remains anchored at the bottom of the current conversation.
- Mobile Inbox keeps a bounded scrollable conversation list and a dedicated thread viewport.
- Replaced the very short single-tone notification beep with a softer, longer two-tone chat chime.
- The improved notification sound is used consistently for new messages on both the staff Inbox and visitor chat.

## 1.2.4 — 2026-08-15
### Live messaging workflow
- Live chat requires the visitor's name and email address.
- A staff chat reply that remains unread for two minutes is emailed to the visitor; active visitors who read it in chat do not receive a duplicate email.
- Visitor name is now required before starting live chat so staff can distinguish conversations.
- Visitor chat persists across public-page navigation; an open chat reopens on the next page, while an intentionally closed chat remains closed.
- Visitor chat polls automatically and plays a short sound when a genuinely new staff reply arrives.
- Communications Inbox is now a two-pane live messaging workspace with all conversations visible beside the current thread.
- Conversation list and current thread refresh automatically without page reload.
- Admin receives a short sound when a genuinely new inbound message arrives.
- Replies, internal notes, status changes, assignments and conversation switching are fetch-driven.
- Conversation list shows visitor name, latest-message preview, channel, status and unread count.
- Open/pending, all, and resolved conversation views are available without overwhelming the default screen.

## 1.2.3 — 2026-08-15
### Staff message alerts
- New live chat, website-form and inbound SMS messages can notify staff automatically.
- Communications Inbox shows a live unread badge in DivisionDesk administration.
- On-site staff alerts link directly to the conversation.
- Email alerts are sent for new conversations by default; Advanced can email every inbound message.
- Browser push can be enabled independently on each staff device.
- Optional SMS alerts can be sent to configured staff numbers.
- Opening a conversation marks its associated staff alerts read.
- Staff Alerts settings save with fetch and include plain-language readiness/help.

## 1.2.2 — 2026-08-15
### Critical fix
- `communications-chat.php` and all other generated Communications public endpoints are now ensured whenever the module registers.
- Upgraded installations self-heal if an earlier update did not regenerate public endpoints.
- Removed suppressed writes from endpoint generation.
- Endpoint generation now fails loudly when `public/` is unavailable/unwritable or a generated file cannot be written.
- Final required-file verification runs before endpoint generation returns success.
- Existing generated files are rewritten only when contents differ.

### Regression tests
- Fresh endpoint generation.
- Upgrade simulation beginning from the pre-chat endpoint set.
- Missing-chat self-healing.
- Idempotent regeneration.
- Failure-path test proving an invalid public path no longer silently succeeds.

## 1.2.1 — 2026-08-15
### Critical upgrade fix
- Replaced the old single-table `Schema::ensure()` shortcut with a sequential migration ledger.
- Existing Communications installations now run every missing migration in natural version order instead of returning early when the original templates table already exists.
- Live-chat migration `003_live_chat.php` therefore runs correctly during module update, not only on fresh installs.
- Migration failures are transactional where supported and identify the exact migration that failed.
- Schema completion is checked after migrations.

### Packaging
- `addon.json` and `manifest.json` explicitly declare `package_type: module`.
- Version bumped to 1.2.1 so it cannot collide with the rejected/staged 1.2.0 package history.

## 1.2.0 — 2026-08-15
### Completed
- Site-wide live chat is automatically injected on public pages when Communications is enabled; no floating widget placement is required.
- Chat uses a speech-bubble icon, fetch-driven history/send/poll, secure guest session cookie, unread badge, mobile full-screen UI, office hours/away message, identity requirements, optional avatar/accent and path exclusions.
- Chat conversations and staff replies are fully integrated with the Communications Inbox.
- Contact/Message widget now provides Contact Card and fetch-driven Inline Form layouts; obsolete Floating Button layout removed.
- SMS provider validation now includes stored secrets; Providers includes real SMS test, segment count and administrator-configured approximate cost.
- Web Push VAPID key generation is exposed when the required runtime library is available.
- Reports include normalized provider callback outcomes.
- System Status page explicitly reports operational, configuration-required, dependency-required, disabled and unsupported-external-workflow states.

### Compatibility
- Requires DivisionDesk Core 3.6.4 for automatic public-page integration.
- Coordinated DivisionDesk Server 1.11.4 adds bounded independent DKIM verification and DMARC evaluation via aligned DKIM.

## 1.1.4 — 2026-08-14
### Fixed
- Full Deliverability create/status calls allow up to 20 seconds for bounded DivisionDesk Server analysis.
- Rebuilt directly from the publisher-validated Communications 1.1.2 package to eliminate staging ambiguity from the rejected 1.1.3 package.

## 1.1.2 — 2026-08-14
### Improved
- Deliverability modal now displays **Test Coverage** separately from Inbox Probability.
- Unavailable SpamAssassin and reputation checks are shown as `Not checked`/`Unable to check` rather than visually implying failure.
- Authentication shows evidence-aware states: Pass, Fail, Signature Present, Policy Present, or Unknown.
- Content & Links now includes a detailed reputation-query report showing provider, tested IP/domain, DNS response, interpretation and query.
- Reputation results distinguish **Clear**, **Listed**, and **Unable to Check**.
- Recommendations explain excluded/unavailable signals instead of treating them as negative delivery evidence.

## 1.1.1 — 2026-08-14
### Fixed
- Deliverability results now render as a true fixed overlay instead of appearing at the bottom of the Campaigns page.
- Mobile view becomes a full-screen sheet with scrollable details.
- Page scrolling is locked while the modal is open.
- Restored the `TestEmail::send(..., $options)` signature needed to attach the secure live-test correlation header.
- Live status displays mailbox-poll warnings instead of silently waiting forever.

## 1.1.0 — 2026-08-14
### Added
- Instant campaign Preflight Analysis.
- Full Deliverability Test through `mailtest@divisiondesk.com`.
- Secure DivisionDesk Server create/status test workflow.
- Actual campaign is sent through the site's configured SMTP transport with a correlation header.
- Responsive circular Inbox Probability gauge with gradual deep-red → red → orange → yellow → green progression.
- Large desktop modal becomes a full-screen mobile sheet.
- Live polling states: sending, waiting, received/analyzing, complete.
- SpamAssassin, authentication, blocklist, structure, content/link and recommendations tabs.
- Fetch-driven workflow; Campaign composer never reloads during testing.

### Changed
- Inbox Probability is explicitly presented as a DivisionDesk estimate, not a receiving-provider guarantee.

## 1.0.7 — 2026-08-14

### Fixed
- Fixed Campaign fetch actions returning Administration HTML before JSON.
- AJAX Campaign requests now authenticate/authorize without rendering `AdminUi::start()` first.
- CSRF verification is handled inside the JSON request error path.
- AJAX responses are explicitly JSON and `Cache-Control: no-store`.

### Diagnostics
- If a future fetch request receives non-JSON content, DivisionDesk shows a short excerpt of the actual HTTP response instead of directing the administrator to a server log that may contain no error.

## 1.0.6 — 2026-08-14

### Fixed
- Fixed `SMTP host and a valid envelope/From email are required` when Core has a valid From address but the optional envelope sender is blank.
- Empty `envelope_from` now correctly falls back to Core `from_email`.

### Changed
- Campaign **Send Email Test** and **Save Campaign** now use `fetch()` and display success/errors in place.
- Transport/validation errors no longer refresh the Campaigns page or clear the composer.
- Non-AJAX fallback restores posted campaign fields after a server-rendered error.
- Submit buttons show a busy state and duplicate submissions are prevented.

### UX direction
- Fetch/AJAX-style in-place actions are the preferred DivisionDesk interaction model where practical.
- User-entered form data should survive errors rather than returning to blank forms.

## 1.0.5 — 2026-08-14

### Fixed
- Fixed campaign test failure `List-Unsubscribe must be HTTPS or mailto.`
- Core relative/base-path URLs are no longer inserted directly into email headers.
- HTTPS web requests automatically establish a canonical DivisionDesk public site URL for Communications.
- Background campaign jobs reuse the stored canonical HTTPS site URL.
- Local/LAN/non-HTTPS installations fall back to a standards-valid `mailto:` List-Unsubscribe target instead of emitting an invalid relative URL.
- `List-Unsubscribe-Post: List-Unsubscribe=One-Click` remains limited to actual HTTPS unsubscribe endpoints.
- Avoids duplicating the Core base path when building absolute unsubscribe URLs.

### Diagnostics
- Communications Providers and Deliverability now show whether bulk email is using HTTPS one-click unsubscribe or the mailto fallback.

## 1.0.4 — 2026-08-14

### Fixed
- Communications now reads the existing DivisionDesk Core **Email Delivery** configuration for SMTP and From settings.
- Campaign Email Test no longer incorrectly reports SMTP as unconfigured when Core SMTP is already working.
- SMTP password is consumed from Core Mailer configuration; Communications no longer expects a duplicate `communications.smtp.password`.
- Blank EHLO/HELO remains blank in configuration and is resolved automatically by the mail transport at connection time.
- Campaign and queued email failures now identify the specific missing Core Email Delivery setting.

### Changed
- Communications → Providers no longer presents a second SMTP configuration form.
- The Providers page shows Core email readiness/status and links directly to the global Email Delivery page.
- Communications-owned provider settings are now limited to SMS and Web Push.

## 1.0.3 — 2026-08-14

### Fixed
- Fixed Campaigns buttons appearing to do nothing with Chrome error `An invalid form control with name='push_url' is not focusable`.
- Push URL, image, icon and badge fields now accept DivisionDesk template variables such as `{{site.url}}` without HTML5 URL validation blocking form submission.
- **Send Email Test** now uses `formnovalidate` so hidden/unrelated campaign channel fields cannot prevent a transport/template test from reaching PHP.

## 1.0.2 — 2026-08-14

### Fixed
- Built-in templates now self-heal if a previous installation or upgrade left `communications_templates` empty.
- Added upgrade migration 002 so 1.0.2 reliably invokes the idempotent template seeder after upgrading.
- Module registration, Campaigns, and Templates defensively restore missing built-ins without overwriting existing customized templates.
- Corrected Campaign list column rendering for topic, channels, schedule, deliveries and actions.

### Added
- Rebuilt Campaigns as a polished multi-channel composer.
- Template selection now immediately loads the template subject, styled HTML, plain-text version, SMS text and push payload into the composer.
- Rich HTML email editor with formatting controls and HTML-source toggle.
- Sandboxed email preview and push-notification preview.
- Immediate single-recipient SMTP campaign test using the production Communications email builder, including multipart HTML/text, Date, Message-ID, List-Unsubscribe and one-click unsubscribe headers.
- Improved channel cards/tabs, SMS character count, audience/timing controls and contextual deliverability guidance.
- Redesigned Template Library with cards, statistics, editor, and Restore Missing Built-ins control.
- Upgraded built-in Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Events, Dues Renewal, Welcome, Login Code, Application Status and Contact Response templates with polished inline email styling.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer; Core 3.6.1 is recommended.

## 1.0.1 — 2026-08-14

### Fixed
- Fixed fresh installation failure: `SQLSTATE[HY000]: General error: 1 no such table: communications_templates`.
- Communications now ensures its schema exists before seeding built-in templates.
- Install, enable and update entry points are safe against a partially completed 1.0.0 installation.
- Existing `CREATE TABLE IF NOT EXISTS` migration statements make recovery non-destructive.

### Compatibility
- Works with DivisionDesk Core 3.6.0 and newer.
- Core 3.6.1 separately corrects the generic module lifecycle ordering for all modules.

## 1.0.0 — 2026-08-14

### Added
- Multi-channel campaign model for Email, SMS, Push and on-site delivery.
- Membership Manager audience adapter with active-member, Camp and role targeting.
- Shared background delivery jobs using DivisionDesk Core 3.6 Job Queue.
- Multipart HTML/plain-text email construction with Date, Message-ID, Reply-To, List-ID, List-Unsubscribe and one-click unsubscribe headers where appropriate.
- Non-transactional email footer with physical/site address and unsubscribe link.
- Email header-injection safeguards.
- Deliverability Center with SMTP, sender, SPF and DMARC checks plus DKIM guidance.
- Suppression system for opt-outs, provider failures and invalid destinations.
- Built-in communication templates: Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Event Announcement, Event Reminder, Registration Confirmation, Dues Renewal, Welcome, Login Code, Application Status and Contact Response.
- SMS provider abstraction with Twilio, Amazon SNS and Telnyx outbound adapters.
- Normalized Twilio errors for invalid, landline/non-SMS, unreachable and opted-out numbers.
- Automatic permanent SMS suppression for selected permanent provider failures.
- STOP/START handling for inbound SMS.
- Incoming SMS webhook/conversation handling for Twilio and Telnyx.
- Standards-oriented Web Push subscription database and service worker.
- VAPID Web Push adapter integration point.
- Rich push payload model: title, body, URL, image, icon, badge, actions, tag, TTL, urgency and require-interaction.
- Unified Conversations Inbox for website/contact/SMS messages.
- Public Contact Us / Website Messaging system.
- Member Communication Preferences page.
- Contact, Announcement and Communication Preferences widgets.
- NotificationService API for other DivisionDesk modules to queue transactional or bulk notifications.
- Notification Rule trigger/action foundation.
- Provider settings using Core encrypted Secret Vault.
- Delivery reports, provider-event history and configurable retention foundation.

### Security
- Provider secrets are encrypted by Core 3.6 Secret Vault.
- Twilio webhook signatures are validated before incoming events are trusted.
- Telnyx Ed25519 webhook verification is supported when a public verification key is configured.
- Email header values reject CR/LF injection.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer.
Module

Events 1.1.25

development · published · 2026-09-25T21:34:00+00:00

Adds registration timing enforcement: configurable close time; blank defaults to event start; existing enabled events are converged to that default; public registration closes at deadline/start. Public event listings continue to exclude started/past occurrences.

Full package changelog
# Events 1.1.25

- Adds organization scope to events. Existing events converge to Division/default.
- Camp Commander and Camp Adjutant may create, edit, publish/archive, and delete only events owned by their own Camp.
- Camp-scoped authorization is enforced server-side for save, cancel/archive, and delete operations.
- Camp officers see only their Camp events in Events administration; Division event administrators retain Division-wide authority.
- Camp event saves use the module-owned scoped save action instead of the legacy global Core save endpoint.

# Events 1.1.24
- Registration Closes remains a configurable date/time.
- Leaving it blank now explicitly means registration closes when the event begins.
- Existing registration-enabled events with no close time are converged to their event start so Core's server-side registration endpoint rejects late/direct submissions.
- The module editor synchronizes Core and Events registration timing columns after each save.
- Public registration shows a closed/not-yet-open message instead of a form outside the allowed window.
- `Register Now` is not shown after registration closes.
- Verified public Events list/upcoming/featured queries already exclude occurrences once their start time has passed.
- No Core update required.

# Events 1.1.23
- FIX: The blank public `Events` title area is now suppressed using the actual DivisionDesk Builder heading markup (`cms-block--heading`) on event-detail pages.
- The previous 1.1.22 selector looked for a `cms-hero`, which is not what this page uses; therefore it could never hide the title shown in the test screenshot.
- The Events listing page remains unchanged.
- Retains 1.1.22 tab-scroll, registration UI, and Schedule editor toolbar fixes.
- No Core change.

# Events 1.1.22
- FIX: Public tab clicks no longer jump the browser back to the top of the event card; the native tab radio state is fixed to the viewport rather than positioned at the article top.
- FIX: Event-detail pages hide the generic CMS `Events` hero/blank title area. The Events listing page is unchanged.
- FIX: Schedule rich-text toolbar buttons have explicit contrasting backgrounds/text so formatting icons remain visible.
- FIX: `Register & Pay Online` is shown only when the installed Finance module exposes the supported Events checkout contract.
- Paid Events registrations work with Finance 1.2.9+; `Register — Pay Later` remains available independently.
- No Core changes.

# Events 1.1.21
- FIX: Public Overview / Schedule / Location / Registration tabs no longer depend on JavaScript. They use native radio/label state plus CSS, so exactly one panel is selected without a JS tab handler.
- FIX: Register Now switches directly to the Registration panel using that same native mechanism.
- FIX: Corrected an undefined `$eventId` reference in the generated registration JavaScript; the real event ID is now used.
- FIX: Standalone Registration Button widget no longer inherits tab-only hidden styling.
- No Core, Finance, or Membership Manager changes.

# Events 1.1.20
- Removed attendee type selection from the new public registration flow.
- Member number and Camp name/number are available on every registration and are optional except member number on explicitly members-only events.
- Additional Guests is built in and defaults to $0 additional registration fee.
- Event admins may explicitly apply the base registration fee to each additional guest.
- Add-on quantities are independent of primary registrant/guest count.
- Blank add-on quantity means zero.
- Quantity add-ons with per-item choices allow blank choices after a confirmation warning.
- Added a canonical Core rich-text Schedule editor and public Schedule rendering.
- Preserves historical attendee-type data for existing registrations.
- Requires Core 4.6.12+.

# Events 1.1.19

- Public event tabs are now genuinely mutually exclusive. Overview, Schedule, Location and Registration occupy the same content region; inactive panels are both hidden and `display:none`.
- `Register Now` activates the Registration panel instead of appending/scrolling to a second copy of event content.
- Attendee types may be removed from active configuration even when historical registrations reference them; in that case the type is archived and history is preserved.
- An active attendee type named `Guest` automatically creates an `Additional Guests` registration control using that Guest price. Selecting 2 guests creates exactly 2 required guest-name fields.
- Priced Select/Radio options with choices are normalized to `quantity_choice`, so a Banquet priced per person gets a quantity selector and one Beef/Chicken/etc. selector per purchased unit.
- Reducing a guest/option quantity removes excess DOM controls, so hidden stale names/choices are not submitted.
- Requires Core 4.6.11+ because Core owns authoritative server-side quantity normalization and pricing.

# Events 1.1.18
- Registration is now a true event tab instead of content appended below Overview.
- Primary attendee collects full name, address, phone and email; member-only registrations also require member number and Camp name/number.
- Logged-in members auto-fill from the Membership Manager provider when available.
- Adds Guest Names options: selecting quantity N creates exactly N guest-name fields.
- Adds Quantity + per-item choice options: quantity N creates exactly N choice selectors, e.g. Beef/Chicken for each meal.
- Reducing a quantity removes and clears excess guest/choice inputs immediately.
- Quantity pricing updates live and zero quantity means no charge.
- Hides legacy duplicate `Registration Fee` add-ons when attendee type pricing already provides the base registration price.
- Retains 1.1.17 pay-now/pay-later and duplicate-submit fixes.

# Events 1.1.17
- Fixes duplicate registrations caused by Core and Events both submitting the same form.
- Fixes Save/Publish redirecting to legacy Core Events admin.
- Adds Register & Pay Online / Register — Pay Later and a live registration/add-on/total breakdown.
- Finance completion marks the matching registration paid/confirmed.
- My Events matches member ID or email and is moved before the site footer.
- Retains 1.1.16 toggle persistence and 1.1.15 rich public detail restoration.

# Events 1.1.16

- Fixes the Events module editor Registration switch turning itself back off after Save.
- Core `registration_enabled` and Events `registration_mode` are now explicitly synchronized.
- The module's post-save integration action writes both fields, so public registration becomes available immediately after enabling it.
- Event reads treat Core's `registration_enabled` compatibility field as authoritative when an older/stale `registration_mode` disagrees.
- Waitlist state is also carried through the same module extras save.
- All 1.1.15 public detail/card/routing and 1.1.13 registration/check-in/refund functionality is retained.

# Events 1.1.15

- Rebuilt from the untouched Events 1.1.13 package, not from 1.1.14.
- Preserves the 1.1.13 rich registration, QR/check-in, cancellation/refund, My Events, attendee/options and Finance integration code.
- Adds only the missing `days()`, `daysUntil()` and `startingPrice()` helpers required by the existing public detail renderer.
- Upcoming/Next/Featured event cards are styled, clickable and show `Cost: Starting at $xx.xx` for paid events.
- `/events?event=ID` now hands the Events page into the existing full Event Detail / Registration renderer instead of looping to the same list card.
- Adds narrow duplicate-submit protection to the legacy and current event editors.

# Changelog

## 1.1.13

- Fixed the false Core "Check-in code is invalid" toast after a successful short confirmation-code check-in by removing the native form-submit path entirely. The Events check-in control now uses one explicit AJAX action for short codes and only calls Core directly for signed credentials.
- Quick Actions on the Events dashboard is now a working no-JavaScript dropdown with direct links to Check-in, Registrations, Attendees, Reports and Settings.
- Removed the duplicated Core module title/card from Events administration and expanded the Events application shell to the available admin width without modifying Core.
- Expanded My Events management: members can open registration details, add guests through Core Registration 2.0 (including required guest options/add-ons), add available zero-cost options, remove options only when cancellation/refund policy allows, and cancel the full registration when permitted.
- Paid option additions are intentionally blocked before mutation when Core/Finance has no safe incremental-charge contract; the module will not silently add an unpaid charge to an already-paid registration.
- Paid refundable option removal creates an itemized refund request for Finance review instead of silently changing historical payment data.

## 1.1.12
- Audited against DivisionDesk Core 4.4.4 without changing Core.
- Fixed camera flow so permission is requested before decoder capability checks; added native BarcodeDetector + jsQR fallback scanning.
- Check-in now accepts a full QR URL, signed token, or visible confirmation code such as `761A88ED8D`.
- Bypassed the Core subdirectory QR double-prefix issue in the Events public flow by generating a correct module-owned QR from the signed credential.
- Added SDK-based `/my-events` management/cancellation controls for signed-in members.
- Aligned runtime data access with Core Registration 2.0 (`first_name`/`last_name`, `confirmed`/`waitlisted`, `price_cents`, `event_registration_options`, `event_registration_answers`).
- Refund calculations now use Core paid totals and answer price snapshots when available.
- Prevented Events uninstall from dropping Core-owned event/registration tables.

## 1.1.11
- Added attendee self-cancellation using confirmation code + registration email, with per-event cancellation controls and cutoff date.
- Added event-level refund modes plus per-attendee-type and per-option refund policies (inherit/refundable/nonrefundable/manual).
- Paid cancellations create auditable itemized refund requests; Events never moves money directly and leaves actual refund processing to Core/Finance.
- Added optional automatic waitlist promotion when a confirmed registration cancels.
- Reworked confirmation URL normalization so the configured DivisionDesk base path is never prepended twice by Events.
- Expanded schema convergence and Diagnostics for cancellation/refund fields and refund-request storage.
- Documented that the QR image on Core's confirmation/badge page is Core-owned; Events Check-in safely extracts the signed token even if a scanned QR contains a URL.

## 1.1.9
- Prevented duplicate public registration submissions with a single raw same-origin request, submit locking, button disabling, and a short post-success lock.
- Public registration now explicitly renders every active option/add-on and labels each one Required or Optional; only required fields receive browser validation.
- Successful registration stays in the Events registration experience rather than automatically following Core legacy redirects.
- Confirmation URLs returned by Core are normalized to the configured DivisionDesk public base path for subdirectory installs.
- QR check-in accepts a raw signed credential or extracts token/credential/checkin_token/code values from a scanned QR URL.
- Removed the module link to undocumented `/events-badge.php`, which could produce a 404; registrations now link to the supported Check-in workspace.

## 1.1.8
- Removed duplicate Core/page heading presentation from Events module pages and widened the Events workspace.
- Published one-off events are now immediately discoverable by public Events widgets even if an occurrence row has not yet been materialized.
- Added an in-module public event preview so administrators can test the exact public event/registration experience before placing widgets.
- The Registration Button widget now resolves the selected/next published event and exposes a working registration flow instead of an orphan anchor.
- Event presentation fields (summary, featured image, city/state, timezone, all-day/featured flags) are persisted after the frozen Core save contract through an Events Smart Action.
- Public widget queries now fall back safely to base event dates when occurrence materialization is not available.

- Made event options/add-ons truly optional and removed invalid nested forms.
- Added multiple option/type creation controls and remove actions.
- Added cancel/archive and guarded permanent delete event actions.
- Kept successful saves inside the polished Events module editor.
- Expanded responsive layout to a centered wide workspace instead of a cramped Core column.

## 1.1.6
- Full runtime schema convergence for registration types, registration fields, and categories, including active/sort_order and every column referenced by current queries.
- Diagnostics/schema health now verifies those query-critical columns before reporting current.

# Changelog

## 1.1.6
- Fixed Dashboard/Events/Check-in compatibility with Core-created event rows that use `location` rather than `location_name`.
- Added Core 4.3.4 event-contract compatibility fields non-destructively and synchronized legacy display fields.
- Fixed partial output-buffer leakage so a caught page exception no longer duplicates the Events rail/layout.
- Event saves now return to the DivisionDesk Events module editor instead of the legacy Core `/events-admin.php` screen.
- Registration type/option saves stay inside the module UI instead of following Core legacy redirects.
- Removed negative-margin module layout behavior that could collide with the Core admin shell.
- Diagnostics now verifies both Core event-contract fields and Events display fields.

## 1.1.4
- Added request-time schema health checking and idempotent self-healing so Store replacements no longer depend on Install/Update lifecycle hooks.
- Schema repair directly converges missing Events/Registration 2.0 tables and columns without deleting existing event data.
- Diagnostics exposes automatic repair failures and retains the explicit Repair / Verify Events Schema Smart Action.
- Schema version is verified and recorded as 1.1.4 only after required objects are confirmed present.

## 1.1.2
- Stabilized Dashboard, Venues, Categories and Settings with defensive data access.
- Added module-owned exception handling so useful errors are visible instead of being swallowed by the Core page wrapper.
- Added Diagnostics page for database driver, schema version, required tables and Registration 2.0 columns.
- Added migration 003 to verify/repair required v1.1 schema columns and record schema version 1.1.2.
- Preserved the approved Events v1.1 admin visual system and Platform 1.1 API/SDK architecture.

# Events Changelog

## 1.1.0 — 2026-08-28
- Rebuilt administration around Developer Platform 1.1 module-owned admin pages and the approved Events dashboard visual language.
- Added Registration 2.0 attendee types, priced options/add-ons, capacities, waitlists and member-only flags.
- Added QR/manual check-in workspace and registration schema fields for signed check-in credentials, confirmation codes and check-in timestamps.
- Added Reports, Attendees, Waitlists, Venues, Settings and API workspaces.
- Added setup wizard, dashboard contribution, search provider, Smart Action, integration listeners and current SDK job registration.
- Added public Event Detail / Registration and Registration Button Builder widgets.
- Event mutations use Core Events / Registration 2.0 endpoints; payments/refunds remain owned by central Finance/Payments integration.
- Removed legacy standalone admin chrome from the primary experience.

## 1.0.0 — 2026-08-14
- Initial Events module baseline.

## 1.1.2
- Schema repair release: install/update now explicitly converges partial Events schemas.
- Creates missing categories, venues, settings, registration fields and registration types tables.
- Adds missing Registration 2.0 columns including registration_mode, amounts, confirmation and QR check-in fields.
- Adds Diagnostics Repair / Verify Events Schema action.
- Clarifies recurring-event generation horizon setting.
Module

Membership Manager 1.3.24

development · published · 2026-09-25T21:33:57+00:00

Adds roster sorting by name, camp, or status; repairs authorized CSV export to use complete member fields; and adds printable PDF roster export while preserving scope and export permissions.

Full package changelog
# Membership Manager 1.3.24

- Adds Events create/edit/publish/delete access to the standard Camp Commander and Camp Adjutant DivisionDesk role presets. Events 1.1.25 enforces Camp ownership server-side, so these permissions do not grant authority over other Camps or Division events.
- Preserves roster column sorting and CSV/PDF export fixes from 1.3.23.

# 1.3.23 QA
- Replaces the roster Sort dropdown with clickable Member, Camp, and Status column headings.
- Clicking the active column toggles ascending/descending order with ASCII-style up/down arrows; clicking another sortable column immediately changes the sort.
- Preserves 1.3.22 CSV/PDF export fixes and all existing roster filtering, scope, dues, role, and Finance behavior.

# 1.3.22 QA
- Added roster sorting by Name, Camp, or Status.
- Fixed CSV export by exporting complete authorized member rows instead of the lean on-screen list projection.
- Added authorized printable PDF roster export.
- Preserved existing scope enforcement and `rosters.export` permission checks for both formats.

# Changelog

## 1.3.21 - suEXEC-Safe Public Endpoint Permissions

- Changes generated public PHP endpoint permissions from `0664` to `0644` so Apache suEXEC does not reject them as writable by others.
- Changes the generated Rosters API directory mode from `0775` to `0755` for the same shared-hosting compatibility reason.
- Keeps the 1.3.20 create-if-missing behavior so normal bootstrap/heartbeat requests do not rewrite existing Membership Manager endpoint shims.

## 1.3.20 - Public Endpoint Self-Repair
- Ensures Membership Manager public endpoint shims during `Addon::register()` so missing `membership-*.php` files are recreated on a normal module bootstrap.
- Existing endpoint files are no longer rewritten merely because the addon is registered or the scheduler runs.
- Keeps explicit write verification/errors when a missing endpoint actually needs to be created.
- Root `.htaccess` is only rewritten when the Rosters API block is genuinely absent.
- Preserves the v1.3.18 MySQL reserved-word compatibility fixes and the v1.3.19 endpoint repair migration.

## 1.3.19 - QA
- Ensures Membership Manager public endpoint shims are generated from migration 008, covering install/reinstall paths that run migrations but skip the optional module lifecycle hook.
- Makes critical PublicEndpoints writes fail explicitly with the exact path instead of silently suppressing filesystem errors.
- Verifies all required membership endpoint shims exist after generation.
- Retains the v1.3.18 MySQL reserved-word compatibility fixes.

# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Membership Manager 1.3.23

development · published · 2026-09-25T21:11:47+00:00

Adds roster sorting by name, camp, or status; repairs authorized CSV export to use complete member fields; and adds printable PDF roster export while preserving scope and export permissions.

Full package changelog
# 1.3.23 QA
- Replaces the roster Sort dropdown with clickable Member, Camp, and Status column headings.
- Clicking the active column toggles ascending/descending order with ASCII-style up/down arrows; clicking another sortable column immediately changes the sort.
- Preserves 1.3.22 CSV/PDF export fixes and all existing roster filtering, scope, dues, role, and Finance behavior.

# 1.3.22 QA
- Added roster sorting by Name, Camp, or Status.
- Fixed CSV export by exporting complete authorized member rows instead of the lean on-screen list projection.
- Added authorized printable PDF roster export.
- Preserved existing scope enforcement and `rosters.export` permission checks for both formats.

# Changelog

## 1.3.21 - suEXEC-Safe Public Endpoint Permissions

- Changes generated public PHP endpoint permissions from `0664` to `0644` so Apache suEXEC does not reject them as writable by others.
- Changes the generated Rosters API directory mode from `0775` to `0755` for the same shared-hosting compatibility reason.
- Keeps the 1.3.20 create-if-missing behavior so normal bootstrap/heartbeat requests do not rewrite existing Membership Manager endpoint shims.

## 1.3.20 - Public Endpoint Self-Repair
- Ensures Membership Manager public endpoint shims during `Addon::register()` so missing `membership-*.php` files are recreated on a normal module bootstrap.
- Existing endpoint files are no longer rewritten merely because the addon is registered or the scheduler runs.
- Keeps explicit write verification/errors when a missing endpoint actually needs to be created.
- Root `.htaccess` is only rewritten when the Rosters API block is genuinely absent.
- Preserves the v1.3.18 MySQL reserved-word compatibility fixes and the v1.3.19 endpoint repair migration.

## 1.3.19 - QA
- Ensures Membership Manager public endpoint shims are generated from migration 008, covering install/reinstall paths that run migrations but skip the optional module lifecycle hook.
- Makes critical PublicEndpoints writes fail explicitly with the exact path instead of silently suppressing filesystem errors.
- Verifies all required membership endpoint shims exist after generation.
- Retains the v1.3.18 MySQL reserved-word compatibility fixes.

# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Membership Manager 1.3.22

development · published · 2026-09-25T21:06:18+00:00

Adds roster sorting by name, camp, or status; repairs authorized CSV export to use complete member fields; and adds printable PDF roster export while preserving scope and export permissions.

Full package changelog
# 1.3.22 QA
- Added roster sorting by Name, Camp, or Status.
- Fixed CSV export by exporting complete authorized member rows instead of the lean on-screen list projection.
- Added authorized printable PDF roster export.
- Preserved existing scope enforcement and `rosters.export` permission checks for both formats.

# Changelog

## 1.3.21 - suEXEC-Safe Public Endpoint Permissions

- Changes generated public PHP endpoint permissions from `0664` to `0644` so Apache suEXEC does not reject them as writable by others.
- Changes the generated Rosters API directory mode from `0775` to `0755` for the same shared-hosting compatibility reason.
- Keeps the 1.3.20 create-if-missing behavior so normal bootstrap/heartbeat requests do not rewrite existing Membership Manager endpoint shims.

## 1.3.20 - Public Endpoint Self-Repair
- Ensures Membership Manager public endpoint shims during `Addon::register()` so missing `membership-*.php` files are recreated on a normal module bootstrap.
- Existing endpoint files are no longer rewritten merely because the addon is registered or the scheduler runs.
- Keeps explicit write verification/errors when a missing endpoint actually needs to be created.
- Root `.htaccess` is only rewritten when the Rosters API block is genuinely absent.
- Preserves the v1.3.18 MySQL reserved-word compatibility fixes and the v1.3.19 endpoint repair migration.

## 1.3.19 - QA
- Ensures Membership Manager public endpoint shims are generated from migration 008, covering install/reinstall paths that run migrations but skip the optional module lifecycle hook.
- Makes critical PublicEndpoints writes fail explicitly with the exact path instead of silently suppressing filesystem errors.
- Verifies all required membership endpoint shims exist after generation.
- Retains the v1.3.18 MySQL reserved-word compatibility fixes.

# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Finance 1.2.13

development · published · 2026-09-25T17:39:08+00:00

Adds Square as a first-class Finance payment provider while preserving the existing FinanceService integration contract used by Storefront, Events, Membership Manager, SCV Operations and other modules. Includes Square Web Payments card tokenization, Payments API processing, refunds, verified webhooks, sandbox/production settings and provider fee policy.

Full package changelog
# Finance 1.2.13 QA

- Added Square as a first-class provider beneath the existing FinanceService contract.
- Added Square Sandbox/Production configuration using Core SecretVault for access token and webhook signature key.
- Added embedded Square Web Payments SDK card tokenization; raw card data never enters DivisionDesk.
- Added Square Payments API creation/verification, refunds, webhook signature validation, event deduplication and payment status mapping.
- Preserved existing Stripe, PayPal, ledger, source-module identity, completion events, durable integration delivery, refund and convenience-fee contracts.
- No database migration required.

## 1.2.12
- Hardened Finance integration return URL detection and fallbacks.
- Accepts `/root/relative.php`, full same-site `https://host/...`, and `page.php` / `subdir/page.php` relative to the current request folder.
- Normalizes `.` / `..` path segments before storage.
- Rejects protocol-relative URLs, external hosts, CR/LF injection, and unsupported schemes.
- Preserves the already-working Events checkout, existing local-path integrations, Storefront/Membership behavior, and configurable accounting mappings.

## 1.2.11
- FIX: Events online checkout no longer fails when Core supplies its confirmation return URL as an absolute same-site URL.
- Finance now accepts either a local `/path` or an `http(s)` URL on the current DivisionDesk host and normalizes the latter back to a local path.
- Off-site return URLs, protocol-relative URLs, CR/LF injection, and unsupported schemes remain rejected.
- This fixes both the initial `Register & Pay Online` redirect and `Pay Balance Now` on existing pending-payment Event confirmations.
- Retains the configurable Finance accounting mappings introduced in 1.2.10.
- No Core update is required.

## 1.2.10
- Added Finance-owned configurable accounting mappings under Accounts & Funds.
- End organizations can choose the destination Fund and Income Account for National, Division, and Camp dues; National, Division, and Camp late fees; Membership donations; Events registrations/add-ons; Storefront sales defaults; and convenience/processing-fee recovery.
- Existing default accounts are preconfigured automatically, so upgrades remain operational without manual setup.
- Membership checkout now uses the existing Rosters per-level metadata to split National / Division / Camp dues and late fees into their selected mappings without a Rosters update.
- Events checkout no longer hard-codes account 4001; it resolves the organization's Events mapping.
- Generic module checkout resolves a Finance mapping when the caller does not supply explicit fund/account IDs, while preserving explicit user/module selections such as current Storefront settings.
- Refunds continue to reverse the original ledger allocation automatically.
- No Core or other module update is required for this mapping layer.

## 1.2.9
- Publishes the Events checkout contract on a fresh version number.
- `FinanceService::eventRegistrationCheckoutUrl()` creates/reuses on-site Finance checkout for `events / registration / <registration id>`.
- Uses `4001 — Event Registration Revenue` for event registrations and add-ons.
- Preserves Finance 1.2.7 Membership Manager, Storefront, provider, refund, ledger and convenience-fee behavior.

## 1.2.8
- Adds `FinanceService::eventRegistrationCheckoutUrl()` as the stable Events payment handoff.
- Adds `4001 — Event Registration Revenue` as the canonical income account for event registrations and add-ons.
- Event checkouts use stable `events / registration / <registration id>` source identity, so retries reuse the same open/paid Finance request instead of creating duplicate charges.
- Retains the v1.2.7 Membership late-fee/donation allocations and all existing Storefront/refund/provider behavior.

## 1.2.7
- Adds `FinanceService::donationFundOptions()` for designated-donation integrations.
- Membership Manager donations now post to the specific active Finance fund selected for each donation option while using the Designated Donations income account.
- Fixes the historical account-code collision: `0003` remains General Donations and `0005 — Late Fees` is the dedicated late-fee account.
- Retains Storefront checkout/refund contracts, processing-fee handling, duplicate-code friendly errors, statements and existing payment-provider behavior.

# Finance v1.2.6

- Added `FinanceService::refundSourcePayment()` for module-owned refunds through Finance/provider/ledger authority.
- Added `FinanceService::paymentFeePreview()` and shared `PaymentService::processingFeeQuote()` so Storefront can disclose the exact convenience fee before payment without duplicating provider policy.
- Full remaining source refunds include the remaining payer convenience fee.

# Finance 1.2.5

- Added `FinanceService::accountingOptions()` as the stable module-to-module API for active funds and income accounts.
- Account/Fund creation now reports duplicate codes clearly instead of exposing raw SQL constraint errors.
- No Finance checkout validation was weakened; integrating modules must still provide an explicit active fund and income account.

## 1.2.4
- Replaces the misleading generic `checkoutUrl()` membership alias with a true module-neutral checkout contract.
- Requires stable source identity and reuses matching open/paid requests without duplicating orders.
- Rejects reuse when a caller changes the amount under the same source identity.
- Applies Finance-owned processor-fee policy to generic module checkouts.
- Adds validated local post-payment return actions for Storefront and other modules.
- Fixes payment finalization so saved split ledger allocations are posted intact.

## 1.2.3
- Adds configurable processor-fee pass-through using a gross-up calculation so the configured merchant fee can be recovered without reducing the intended dues/donation subtotal.
- Processing fees are provider-specific and calculated after the payer chooses the payment method.
- Adds separate Processing Fee Recovery and Late Fees income accounting.
- Preserves Membership Dues, Late Fees, Designated Donations, and Processing Fee Recovery as separate ledger allocations.
- Adds durable retry delivery for cross-module `finance.payment.completed` events so a successful processor capture is not dependent on the member visiting a reconciliation page.
- Checkout displays the payment subtotal and convenience fee separately and receipts retain the final paid amount.

# 1.2.2

- Completes the Finance-to-Membership Manager payment lifecycle through the Core Integration SDK, adds source-payment reconciliation, membership success actions/receipt links, and clarifies PayPal card checkout UX.

# Changelog

## 1.1.0
- Added Statements & Billing with saved/versioned templates.
- Added prebuilt MRS (Member Renewal Statement).
- Added safe DivisionDesk statement pseudocode with nested conditions, charge/note/total/payment directives.
- Added contextual per-camp dues lookup; unknown is distinct from zero.
- Added single/selected/all-active/camp bulk billing runs with immutable recipient snapshots.
- Added queued bulk email through Communications when available, Core Mailer fallback otherwise.
- Added secure payment link, raw payment URL and QR-code template directives.
- Added multi-allocation payment requests so one combined renewal payment can post to multiple ledger accounts/funds.
- Added edit/delete-or-archive management for funds and ledger accounts.

# DivisionDesk Finance Changelog

## 1.0.0

### Added
- Fund/account ledger with integer-cent monetary storage.
- Separate organizational funds and income/expense ledger accounts.
- Split transactions with server-side balancing validation.
- Manual income, cash/check/Zelle/other payments, and outgoing expenses.
- Secure payment requests with opaque public tokens and expiry support.
- Shared module-facing Finance service for dues, events, applications and future modules.
- Stripe PaymentIntent integration using embedded Stripe Elements.
- PayPal Orders integration using embedded CardFields / PayPal JavaScript SDK.
- Verified Stripe and PayPal webhook handling with idempotent event storage.
- Provider secrets stored through DivisionDesk SecretVault.
- Transaction search/filtering, dashboard summaries, CSV export and audit trail.
- AJAX/fetch-first administration UI with visible loading/error states.

### Security
- Raw card numbers, CVV and sensitive authentication values are never accepted by DivisionDesk PHP endpoints.
- CSRF validation on administrative writes.
- Capability checks on every administration endpoint, independent of UI visibility.
- Idempotency keys on payment creation and webhook event deduplication.

## 1.2.0
- Replaces raw-code-first statement editing with a rich text/email-style editor.
- Adds font formatting, color, size, Insert Block, Insert Field, conditional insertion, Help, Preview, and Send Test.
- Adds safe HTML sanitization and token parsing inside formatted statement HTML.
- Adds automatic syntax/semantic validation while editing.
- Test Send uses a real roster member automatically when the email matches exactly one member, requests a choice for shared addresses, and uses sample data when no member matches.
- Test statements cannot create payments, receivables, statements, or ledger entries; payment links and QR codes resolve to a nonpayable test page.
- Adds camp name/number and camp adjutant contact/address statement variables.
- Preserves generate-review-Bulk Send separation and immutable statement snapshots.

## 1.2.1
- Added `FinanceService::paymentsConfigured()` so other modules can determine whether an enabled processor has usable credentials without reading Finance settings or secrets.
- Added `FinanceService::paymentProviderStatus()` with secret-free provider readiness information.
- Added `FinanceService::membershipDuesCheckoutUrl()` and `checkoutUrl()` as stable checkout handoff APIs for Membership Manager.
- Membership checkout handoffs are idempotent by roster request key and reuse an existing open/paid Finance request instead of duplicating requests.
- Combined dues/donation checkouts split ledger allocations between Membership Dues and Designated Donations while Finance remains authoritative for provider/payment state.
Module

DivisionDesk Storefront 2.6.0

development · published · 2026-09-24T20:11:42+00:00

Full package changelog
# Storefront 2.6.0 QA

- Added configurable shipping calculations: flat per order, per item, first + additional, first + second + additional, and free shipping.
- Existing free-shipping threshold and local pickup remain supported.
- Product shipping classes can override the default calculation using per-class rules.
- Existing installations remain on flat-per-order behavior by default.
- Stabilized Storefront catalog layout above and within the product grid to reduce /shop cumulative layout shift (CLS).

# Storefront v2.6.0

- Uses Core 4.6.56 responsive-image derivatives for product cards: cached proportional WebP variants at quality 50 with `srcset` and `sizes`.
- First visible product image is eager/high-priority for LCP; remaining product-card images use native lazy loading and async decoding.
- Added accessible labels for Storefront search and sort controls.
- Preserves master images, product URLs, catalog data, cart, checkout, Finance, Membership, and commerce behavior.

# Storefront v2.5.8

- Removed only the public shop hero section (`sf-hero`) from the Storefront shop renderer for mobile/LCP performance testing.
- Preserves the trust strip, category section, product controls/grid, cart, checkout, product pages, settings, and all commerce behavior.
- No schema, migration, database, entitlement, Finance, or Membership changes.

# Storefront v2.5.7

- Fixed Storefront administration on current Core by using `RoleManager::can()` / `RoleManager::requirePermission()` for runtime authorization.
- Retains a guarded compatibility fallback for older Core builds that exposed `Capability::can()` / `Capability::require()`.
- Finance remains the required commerce/payment authority, but Storefront administration and catalog management do not require a configured merchant account merely to load.

# Storefront v2.5.6

- Fixed Storefront refunds by using Finance 1.2.6's stable source-refund API.
- Full remaining Storefront refunds now also return the remaining Finance convenience fee to the payer.
- Full order refunds restore tracked inventory exactly once.
- Cart and checkout now disclose Subtotal, Shipping, Convenience Fee, and Total before payment; discount/tax rows appear when applicable.
- Checkout totals update when the shopper switches between Standard Shipping and Local Pickup.
- Storefront stores the verified Finance convenience-fee amount after payment for order/report visibility.

# Storefront 2.5.5

- Fixed Finance 1.2.x checkout contract: Storefront now supplies explicit `fund_id`, `account_id`, and allocation line IDs.
- Added Storefront Settings selectors for active Finance Fund and Store Sales Income Account via Finance's stable public integration API.
- Checkout now fails early with a Storefront-specific configuration message instead of Finance's generic missing-account error.
- No direct Finance-table access was added to Storefront.

# Changelog

## 2.5.4 — 2026-08-30
- Identifies and addresses the live "no changes taking effect" condition as stale addon OPcache bytecode.
- Adds a brand-new migration that executes before Update.php / Addon.php and force-invalidates every Storefront PHP file in OPcache.
- This directly compensates for Core 4.4.4's module installer replacing addon files without addon OPcache invalidation, while the Core updater already invalidates Core PHP files.
- Adds live runtime markers so the loaded Storefront code can be verified conclusively instead of inferred from the package version card.
- No Storefront 2.6.x bump; patch remains on the user-mandated 2.5.x line.


## 2.5.4 — 2026-08-30
- Full Storefront stabilization pass; no incremental test builds are being delivered between 2.4.0 and this package.
- Moves the critical Core registration path into a minimal `Registration` class loaded directly by root Addon.php.
- Registers Website → Content → Storefront, six public components, and six public pages before any optional integration can run.
- Public component renderer now points to the always-loaded Registration class, eliminating custom-autoloader dependency from Core page rendering.
- Optional setup, widgets, search, Finance event listener, Smart Actions, jobs, dashboard, help and capability refresh are isolated so they cannot make the module disappear.
- Adds explicit deterministic Runtime loading for the complete Storefront codebase.
- Reprovisions only Storefront-owned module pages in migration 120 before registration; Core `/store` remains untouched.
- Fixes Finance completion reconciliation request key on the public order page.
- Retains the approved navy/gold Storefront visual system and all catalog/cart/checkout/admin functionality.


## 2.5.4 — 2026-08-30
- Full Core 4.4.4 contract rebuild using the actual uploaded Core source, Developer Platform 1.1.1, Publishing 1.0.5, and Rosters 1.3.5.
- Corrects Storefront administration registration to the exact working Publishing pattern: moduleAdmin('main') plus Registry::admin() under Website / Content.
- Corrects module component registration to Core 4.4.4's actual Registry::component(string,array) contract with `renderer` = `Class::method`.
- Corrects public module-page keys to local keys (`shop`, `product`, etc.) and keeps fully-qualified component IDs.
- Corrects the Store parent navigation key to `storefront:storefront.shop`, matching Rosters' working nested-page contract.
- Moves stale Storefront system-page cleanup into a real Core ModuleMigration so it executes before Addon::register().
- Preserves Core's required `/store` page unconditionally.
- Corrects Update lifecycle method to `Update::update()`.
- Corrects Core CSRF and capability calls to `Csrf::verify()` and `Capability::can/require()`.
- Corrects admin handler, dashboard, widget, event-listener, search-provider, scheduler and setup-wizard signatures.
- Corrects Membership Manager integration to current Addons\Rosters\MemberSession / MemberRepository / DuesCalculator APIs.


## 2.5.4 — 2026-08-30
- Fixes `SQLSTATE[23000] UNIQUE constraint failed: pages.slug` during upgrades from rejected Storefront builds.
- Moves stale-page reconciliation before all new public module-page registration.
- Uses supported Core page cleanup APIs first when available.
- Adds schema-aware direct cleanup fallback that deletes only rows whose Storefront ownership can be proven.
- Reconciles canonical `/shop*` and historical `store-product` / `store-category` Storefront rows.
- Explicitly and permanently excludes Core `/store` from every cleanup path.
- Adds duplicate-slug, DB-fallback, unrelated-user-page, and Core `/store` preservation regression harnesses.


## 2.5.4 — 2026-08-30
- Aligns Storefront with the package-qualified Core component/page IDs documented by working Publishing 1.0.5.
- Keeps callable component registration and `/shop` public root.
- Explicitly preserves Core's required `/store`.
- Adds best-effort cleanup of obsolete Storefront-owned page IDs only through a Core-exposed page cleanup API.
- Reasserts Website / Content / Novice admin placement and module-admin dispatcher/search metadata.


## 2.5.4 — 2026-08-30
- Fixes live admin discovery/navigation and unavailable public component issues after 2.3.1 installed successfully.
- Uses Core ownership-local registration IDs instead of pre-qualified `storefront.*` IDs.
- Registers public module components as callables, matching the active Core component contract.
- Adds signature-aware compatibility for array-metadata and three-argument component registries.
- Moves the public storefront from `/store` to `/shop` because `/store` is reserved by Core for the package Store.
- Adds `page=main` to the standard module-admin dispatcher URL and supplies Website / Content navigation/search metadata.
- Changes Storefront-owned cart/checkout/order slugs to `/shop-cart`, `/shop-checkout`, and `/shop-order` to avoid generic Core/module route collisions.


## 2.5.4 — 2026-08-30
- Corrects the live Core 4.4.4 `Module page requires component.` install failure.
- Registers six Storefront module components before registering their six Core public module pages.
- Public page descriptors now use the required `component` field instead of incorrectly using `handler`.
- Adds an exact regression harness that rejects a page lacking `component` and rejects a page that references an unavailable component.
- Adds compatibility coverage for Core builds exposing the component registry as `component()` rather than `moduleComponent()`.
- Retains the 2.3.0 full commerce/security/migration fixes.


## 2.5.4 — 2026-08-30
- Full corrective audit after live Core 4.4.4 exposed the invalid Registry bulk capability call.
- Removed the nonexistent bulk capability-registration API and rebuilt the live regression harness without it.
- Fixed checkout RecoveryService namespace fatal, server-side repricing/revalidation, shipping-method/address enforcement, Finance handoff cart preservation, exact-once Finance completion, cumulative refunds, tracked-inventory handling, fail-closed auth/CSRF, manual-order inventory, cart maintenance, category cycles and input/URL validation.
- Added refunded-cents upgrade accounting and expanded the release gate to 39 PASS / 0 FAIL.
- Retains Core-owned Store/Category/Product/Cart/Checkout/Order pages, admin/search, Finance 1.2.3 boundary, membership restrictions, persistent carts, layouts and approved public visual structure.


## 2.3.0 — 2026-08-29
- Rebuilt Storefront registration around the current Core 4.4.4 ownership lifecycle.
- Root class is exactly `Addons\\Storefront\\Addon`; `Register.php` is passive and never eagerly registers.
- Uses current `App\\Core\\Registry::moduleAdmin()` with required title/handler/capability and `Registry::modulePage()` for Core-owned Store pages.
- Uses `App\\Core\\Database::connection()` and `App\\Core\\Url::to()` so subdirectory installations work correctly.
- Removed guessed universal/split registry discovery, direct package API routing, and direct package asset URL assumptions.
- Added MySQL/SQLite-aware schema self-healing for fresh installs and upgrades while retaining Storefront data.
- Retains categories, variants, images, product layouts, member restrictions/member pricing, persistent carts, Save for Later, coupons, Finance checkout, merchant fee policy, order fulfillment/tracking/refunds, digital downloads, promotions, reports, receipts and fulfillment notifications.
- Fixed persistent-cart token reuse, variant inventory/price enforcement, and cross-engine inventory decrement SQL.
- Added current-Core lifecycle/registration regression testing and subdirectory URL assertions.
- All prior 2.1.x artifacts are rejected test builds and should not be promoted.
Module

Georgia Camp Directory 0.3.7

development · published · 2026-09-18T14:28:37+00:00

Clean-install schema fix: initializes the authoritative camp organization-unit table when absent, safely adds required fields to older providers without replacing data, retains deterministic lifecycle loading, and keeps the universal Camp Directory name while preserving the existing package slug for upgrade and entitlement compatibility.

Site Template

Georgia Division SCV Signature Site 3.4.3

development · published · 2026-09-18T14:28:19+00:00

Consolidates the complete Georgia site: adds all previously missing informational pages, restores the agreed dropdown navigation, removes duplicate public navigation, uses the three supplied hero images, keeps assets local/migration-safe, and requires Core 4.6.58 hierarchical template navigation support.

Core

DivisionDesk Core 4.6.58

development · published · 2026-09-18T14:28:15+00:00

Complete-site navigation provisioning: hierarchical/authoritative navigation, registry destination reuse, duplicate suppression, plus all 4.6.57 deployment and migration safeguards.

Full package changelog
# DivisionDesk Core 4.6.58 QA — 2026-09-18

- Site Templates can now provision nested primary/footer navigation.
- `navigation_mode: authoritative` hides stale/duplicate menu items rather than leaving old module links beside the template navigation.
- Template URLs automatically reuse matching registered destinations, preserving module/auth behavior instead of replacing it with hard-coded links.
- Retains all 4.6.57 public-root, CLI, asset, theme, lifecycle and domain-migration safeguards.

# DivisionDesk Core 4.6.57 QA — 2026-09-17

- Makes the configured public filesystem root authoritative across CSS, uploads, image derivatives, setup/health checks, module public payload deployment, Core updates, scheduler bootstrap discovery, and complete-site assets. `public_html`, managed `/public`, and subfolder layouts no longer silently diverge.
- Reworks fresh installation around staged verified extraction, protected license authorization, public-root detection/override, noexec-safe runner execution, HTTPS transport fallback, ZIP extraction fallback, disk/writability preflight, and refusal to overwrite an existing application tree.
- Makes module public deployment fail-safe: modern `addon/public` payloads deploy to the configured public root, while legacy lifecycle writes into canonical `/public` are detected and mirrored before a package is recorded installed.
- Unifies fresh module lifecycle execution through `ModuleLifecycle`: `Install::install()` is authoritative with backward-compatible `Install::run()` support, and missing lifecycle classes/methods now fail installation instead of being silently skipped. Failed module setup is disabled/not marked installed so Cubicle cannot report a partial package as successful.
- Makes Core updates deploy package `/public` into the configured public root transactionally instead of recreating a hidden canonical web root; rollback tracks newly deployed public files.
- Adds complete-site asset deployment/verification and required-theme activation support. A site template cannot report success when declared assets or its required installed theme are missing.
- Makes CLI error handling CLI-safe (STDERR/nonzero exit, no HTTP headers/HTML) and removes the scheduler shebang/public-bootstrap assumptions exposed on cPanel/GoDaddy.
- Persists the installer-selected public path into site configuration and deployment settings; external document roots can use a generated application-root marker.
- Extends Move / Relocate to rewrite known self-URL fields when the canonical domain changes while preserving external URLs, and keeps licensing transfer authorization in the existing relocation flow.
- Retains the newest three successful Core rollback backups by default and safely cleans stale generated installer/repository/update staging directories.
- Rewords System Health telemetry self-test events so successful tests are clearly identified as tests rather than application errors.

# DivisionDesk Core Changelog

## 4.6.56 — 2026-09-15
- Added Core responsive-image derivative service at `image.php` for safe local public images.
- Generates proportional cached WebP derivatives on first request and reuses them thereafter.
- Originals are never modified; cache keys include source path, mtime, size, requested width, and quality.
- Adds long-lived immutable browser caching and ETag support.
- Rejects traversal, remote/non-public sources, cache recursion, and unsupported image MIME types.

## 4.6.55 — 2026-09-15

### Improved
- Public pages now load Core, renderer, and active-theme CSS through one versioned, cached `site-css.php` response, preserving cascade order while reducing render-blocking stylesheet requests.
- Member login and verification documents now declare English language metadata and a meta description.
- Member authentication helper/brand text contrast was strengthened for WCAG AA readability.

## 4.6.54 QA
- Preserve administrator navigation parent/order/label choices across registry synchronization; suggested placement now applies only when a registry destination is first provisioned.
- Exclude wildcard `*` from navigation audience capability choices.
- Normalize www/non-www aliases for high-frequency admin badge/alert polling so requests remain on the origin currently serving the admin UI.

## 4.6.53 QA — 2026-09-15
- Adds explicit Up/Down controls for menu items so sibling order can be changed reliably without changing submenu parentage.
- Disables Up on the first sibling and Down on the last sibling.
- Retains drag/drop for hierarchy changes and all 4.6.52 navigation fixes.

## 4.6.53 QA navigation audience refinement
- Fix site-local custom Navigation URLs so root-relative links such as `/news`, `/events`, `/shop`, and `/admin.php` resolve under the configured DivisionDesk base path instead of the domain root, while avoiding double-prefixing already resolved URLs.
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.53 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Site Template

Georgia Division SCV Signature Site 3.4.2

development · published · 2026-09-18T13:59:08+00:00

Self-contained Georgia site package: includes the supplied full-quality hero imagery and crest, verifies required assets after deployment, activates the Georgia Division Signature theme, and removes module-owned duplicate navigation entries from the template defaults.

Theme

Georgia Division Signature 3.4.4

development · published · 2026-09-18T13:59:04+00:00

Deployment and presentation consolidation: uses Core configured public filesystem root (including public_html/subdirectories), seeds the supplied full-quality Georgia hero images, reports asset deployment failures, keeps the full Georgia footer, uses deployment-safe footer URLs, and removes duplicate top-level navigation by canonical destination.

Core

DivisionDesk Core 4.6.57

development · published · 2026-09-18T13:33:04+00:00

Authoritative public-root deployment, transactional public deployment, CLI-safe scheduling/errors, complete-site asset/theme verification, module lifecycle enforcement, and domain-migration safeguards.

Full package changelog
# DivisionDesk Core 4.6.57 QA — 2026-09-17

- Makes the configured public filesystem root authoritative across CSS, uploads, image derivatives, setup/health checks, module public payload deployment, Core updates, scheduler bootstrap discovery, and complete-site assets. `public_html`, managed `/public`, and subfolder layouts no longer silently diverge.
- Reworks fresh installation around staged verified extraction, protected license authorization, public-root detection/override, noexec-safe runner execution, HTTPS transport fallback, ZIP extraction fallback, disk/writability preflight, and refusal to overwrite an existing application tree.
- Makes module public deployment fail-safe: modern `addon/public` payloads deploy to the configured public root, while legacy lifecycle writes into canonical `/public` are detected and mirrored before a package is recorded installed.
- Unifies fresh module lifecycle execution through `ModuleLifecycle`: `Install::install()` is authoritative with backward-compatible `Install::run()` support, and missing lifecycle classes/methods now fail installation instead of being silently skipped. Failed module setup is disabled/not marked installed so Cubicle cannot report a partial package as successful.
- Makes Core updates deploy package `/public` into the configured public root transactionally instead of recreating a hidden canonical web root; rollback tracks newly deployed public files.
- Adds complete-site asset deployment/verification and required-theme activation support. A site template cannot report success when declared assets or its required installed theme are missing.
- Makes CLI error handling CLI-safe (STDERR/nonzero exit, no HTTP headers/HTML) and removes the scheduler shebang/public-bootstrap assumptions exposed on cPanel/GoDaddy.
- Persists the installer-selected public path into site configuration and deployment settings; external document roots can use a generated application-root marker.
- Extends Move / Relocate to rewrite known self-URL fields when the canonical domain changes while preserving external URLs, and keeps licensing transfer authorization in the existing relocation flow.
- Retains the newest three successful Core rollback backups by default and safely cleans stale generated installer/repository/update staging directories.
- Rewords System Health telemetry self-test events so successful tests are clearly identified as tests rather than application errors.

# DivisionDesk Core Changelog

## 4.6.56 — 2026-09-15
- Added Core responsive-image derivative service at `image.php` for safe local public images.
- Generates proportional cached WebP derivatives on first request and reuses them thereafter.
- Originals are never modified; cache keys include source path, mtime, size, requested width, and quality.
- Adds long-lived immutable browser caching and ETag support.
- Rejects traversal, remote/non-public sources, cache recursion, and unsupported image MIME types.

## 4.6.55 — 2026-09-15

### Improved
- Public pages now load Core, renderer, and active-theme CSS through one versioned, cached `site-css.php` response, preserving cascade order while reducing render-blocking stylesheet requests.
- Member login and verification documents now declare English language metadata and a meta description.
- Member authentication helper/brand text contrast was strengthened for WCAG AA readability.

## 4.6.54 QA
- Preserve administrator navigation parent/order/label choices across registry synchronization; suggested placement now applies only when a registry destination is first provisioned.
- Exclude wildcard `*` from navigation audience capability choices.
- Normalize www/non-www aliases for high-frequency admin badge/alert polling so requests remain on the origin currently serving the admin UI.

## 4.6.53 QA — 2026-09-15
- Adds explicit Up/Down controls for menu items so sibling order can be changed reliably without changing submenu parentage.
- Disables Up on the first sibling and Down on the last sibling.
- Retains drag/drop for hierarchy changes and all 4.6.52 navigation fixes.

## 4.6.53 QA navigation audience refinement
- Fix site-local custom Navigation URLs so root-relative links such as `/news`, `/events`, `/shop`, and `/admin.php` resolve under the configured DivisionDesk base path instead of the domain root, while avoiding double-prefixing already resolved URLs.
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.53 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Module

DivisionDesk Storefront 2.5.9

development · published · 2026-09-16T03:17:23+00:00

Full package changelog
# Storefront v2.5.9

- Uses Core 4.6.56 responsive-image derivatives for product cards: cached proportional WebP variants at quality 50 with `srcset` and `sizes`.
- First visible product image is eager/high-priority for LCP; remaining product-card images use native lazy loading and async decoding.
- Added accessible labels for Storefront search and sort controls.
- Preserves master images, product URLs, catalog data, cart, checkout, Finance, Membership, and commerce behavior.

# Storefront v2.5.8

- Removed only the public shop hero section (`sf-hero`) from the Storefront shop renderer for mobile/LCP performance testing.
- Preserves the trust strip, category section, product controls/grid, cart, checkout, product pages, settings, and all commerce behavior.
- No schema, migration, database, entitlement, Finance, or Membership changes.

# Storefront v2.5.7

- Fixed Storefront administration on current Core by using `RoleManager::can()` / `RoleManager::requirePermission()` for runtime authorization.
- Retains a guarded compatibility fallback for older Core builds that exposed `Capability::can()` / `Capability::require()`.
- Finance remains the required commerce/payment authority, but Storefront administration and catalog management do not require a configured merchant account merely to load.

# Storefront v2.5.6

- Fixed Storefront refunds by using Finance 1.2.6's stable source-refund API.
- Full remaining Storefront refunds now also return the remaining Finance convenience fee to the payer.
- Full order refunds restore tracked inventory exactly once.
- Cart and checkout now disclose Subtotal, Shipping, Convenience Fee, and Total before payment; discount/tax rows appear when applicable.
- Checkout totals update when the shopper switches between Standard Shipping and Local Pickup.
- Storefront stores the verified Finance convenience-fee amount after payment for order/report visibility.

# Storefront 2.5.5

- Fixed Finance 1.2.x checkout contract: Storefront now supplies explicit `fund_id`, `account_id`, and allocation line IDs.
- Added Storefront Settings selectors for active Finance Fund and Store Sales Income Account via Finance's stable public integration API.
- Checkout now fails early with a Storefront-specific configuration message instead of Finance's generic missing-account error.
- No direct Finance-table access was added to Storefront.

# Changelog

## 2.5.4 — 2026-08-30
- Identifies and addresses the live "no changes taking effect" condition as stale addon OPcache bytecode.
- Adds a brand-new migration that executes before Update.php / Addon.php and force-invalidates every Storefront PHP file in OPcache.
- This directly compensates for Core 4.4.4's module installer replacing addon files without addon OPcache invalidation, while the Core updater already invalidates Core PHP files.
- Adds live runtime markers so the loaded Storefront code can be verified conclusively instead of inferred from the package version card.
- No Storefront 2.6.x bump; patch remains on the user-mandated 2.5.x line.


## 2.5.4 — 2026-08-30
- Full Storefront stabilization pass; no incremental test builds are being delivered between 2.4.0 and this package.
- Moves the critical Core registration path into a minimal `Registration` class loaded directly by root Addon.php.
- Registers Website → Content → Storefront, six public components, and six public pages before any optional integration can run.
- Public component renderer now points to the always-loaded Registration class, eliminating custom-autoloader dependency from Core page rendering.
- Optional setup, widgets, search, Finance event listener, Smart Actions, jobs, dashboard, help and capability refresh are isolated so they cannot make the module disappear.
- Adds explicit deterministic Runtime loading for the complete Storefront codebase.
- Reprovisions only Storefront-owned module pages in migration 120 before registration; Core `/store` remains untouched.
- Fixes Finance completion reconciliation request key on the public order page.
- Retains the approved navy/gold Storefront visual system and all catalog/cart/checkout/admin functionality.


## 2.5.4 — 2026-08-30
- Full Core 4.4.4 contract rebuild using the actual uploaded Core source, Developer Platform 1.1.1, Publishing 1.0.5, and Rosters 1.3.5.
- Corrects Storefront administration registration to the exact working Publishing pattern: moduleAdmin('main') plus Registry::admin() under Website / Content.
- Corrects module component registration to Core 4.4.4's actual Registry::component(string,array) contract with `renderer` = `Class::method`.
- Corrects public module-page keys to local keys (`shop`, `product`, etc.) and keeps fully-qualified component IDs.
- Corrects the Store parent navigation key to `storefront:storefront.shop`, matching Rosters' working nested-page contract.
- Moves stale Storefront system-page cleanup into a real Core ModuleMigration so it executes before Addon::register().
- Preserves Core's required `/store` page unconditionally.
- Corrects Update lifecycle method to `Update::update()`.
- Corrects Core CSRF and capability calls to `Csrf::verify()` and `Capability::can/require()`.
- Corrects admin handler, dashboard, widget, event-listener, search-provider, scheduler and setup-wizard signatures.
- Corrects Membership Manager integration to current Addons\Rosters\MemberSession / MemberRepository / DuesCalculator APIs.


## 2.5.4 — 2026-08-30
- Fixes `SQLSTATE[23000] UNIQUE constraint failed: pages.slug` during upgrades from rejected Storefront builds.
- Moves stale-page reconciliation before all new public module-page registration.
- Uses supported Core page cleanup APIs first when available.
- Adds schema-aware direct cleanup fallback that deletes only rows whose Storefront ownership can be proven.
- Reconciles canonical `/shop*` and historical `store-product` / `store-category` Storefront rows.
- Explicitly and permanently excludes Core `/store` from every cleanup path.
- Adds duplicate-slug, DB-fallback, unrelated-user-page, and Core `/store` preservation regression harnesses.


## 2.5.4 — 2026-08-30
- Aligns Storefront with the package-qualified Core component/page IDs documented by working Publishing 1.0.5.
- Keeps callable component registration and `/shop` public root.
- Explicitly preserves Core's required `/store`.
- Adds best-effort cleanup of obsolete Storefront-owned page IDs only through a Core-exposed page cleanup API.
- Reasserts Website / Content / Novice admin placement and module-admin dispatcher/search metadata.


## 2.5.4 — 2026-08-30
- Fixes live admin discovery/navigation and unavailable public component issues after 2.3.1 installed successfully.
- Uses Core ownership-local registration IDs instead of pre-qualified `storefront.*` IDs.
- Registers public module components as callables, matching the active Core component contract.
- Adds signature-aware compatibility for array-metadata and three-argument component registries.
- Moves the public storefront from `/store` to `/shop` because `/store` is reserved by Core for the package Store.
- Adds `page=main` to the standard module-admin dispatcher URL and supplies Website / Content navigation/search metadata.
- Changes Storefront-owned cart/checkout/order slugs to `/shop-cart`, `/shop-checkout`, and `/shop-order` to avoid generic Core/module route collisions.


## 2.5.4 — 2026-08-30
- Corrects the live Core 4.4.4 `Module page requires component.` install failure.
- Registers six Storefront module components before registering their six Core public module pages.
- Public page descriptors now use the required `component` field instead of incorrectly using `handler`.
- Adds an exact regression harness that rejects a page lacking `component` and rejects a page that references an unavailable component.
- Adds compatibility coverage for Core builds exposing the component registry as `component()` rather than `moduleComponent()`.
- Retains the 2.3.0 full commerce/security/migration fixes.


## 2.5.4 — 2026-08-30
- Full corrective audit after live Core 4.4.4 exposed the invalid Registry bulk capability call.
- Removed the nonexistent bulk capability-registration API and rebuilt the live regression harness without it.
- Fixed checkout RecoveryService namespace fatal, server-side repricing/revalidation, shipping-method/address enforcement, Finance handoff cart preservation, exact-once Finance completion, cumulative refunds, tracked-inventory handling, fail-closed auth/CSRF, manual-order inventory, cart maintenance, category cycles and input/URL validation.
- Added refunded-cents upgrade accounting and expanded the release gate to 39 PASS / 0 FAIL.
- Retains Core-owned Store/Category/Product/Cart/Checkout/Order pages, admin/search, Finance 1.2.3 boundary, membership restrictions, persistent carts, layouts and approved public visual structure.


## 2.3.0 — 2026-08-29
- Rebuilt Storefront registration around the current Core 4.4.4 ownership lifecycle.
- Root class is exactly `Addons\\Storefront\\Addon`; `Register.php` is passive and never eagerly registers.
- Uses current `App\\Core\\Registry::moduleAdmin()` with required title/handler/capability and `Registry::modulePage()` for Core-owned Store pages.
- Uses `App\\Core\\Database::connection()` and `App\\Core\\Url::to()` so subdirectory installations work correctly.
- Removed guessed universal/split registry discovery, direct package API routing, and direct package asset URL assumptions.
- Added MySQL/SQLite-aware schema self-healing for fresh installs and upgrades while retaining Storefront data.
- Retains categories, variants, images, product layouts, member restrictions/member pricing, persistent carts, Save for Later, coupons, Finance checkout, merchant fee policy, order fulfillment/tracking/refunds, digital downloads, promotions, reports, receipts and fulfillment notifications.
- Fixed persistent-cart token reuse, variant inventory/price enforcement, and cross-engine inventory decrement SQL.
- Added current-Core lifecycle/registration regression testing and subdirectory URL assertions.
- All prior 2.1.x artifacts are rejected test builds and should not be promoted.
Core

DivisionDesk Core 4.6.56

development · published · 2026-09-16T03:17:19+00:00

Adds a safe cached responsive-image derivative service for local public images, producing proportional WebP variants on demand without modifying originals.

Full package changelog
# DivisionDesk Core Changelog

## 4.6.56 — 2026-09-15
- Added Core responsive-image derivative service at `image.php` for safe local public images.
- Generates proportional cached WebP derivatives on first request and reuses them thereafter.
- Originals are never modified; cache keys include source path, mtime, size, requested width, and quality.
- Adds long-lived immutable browser caching and ETag support.
- Rejects traversal, remote/non-public sources, cache recursion, and unsupported image MIME types.

## 4.6.55 — 2026-09-15

### Improved
- Public pages now load Core, renderer, and active-theme CSS through one versioned, cached `site-css.php` response, preserving cascade order while reducing render-blocking stylesheet requests.
- Member login and verification documents now declare English language metadata and a meta description.
- Member authentication helper/brand text contrast was strengthened for WCAG AA readability.

## 4.6.54 QA
- Preserve administrator navigation parent/order/label choices across registry synchronization; suggested placement now applies only when a registry destination is first provisioned.
- Exclude wildcard `*` from navigation audience capability choices.
- Normalize www/non-www aliases for high-frequency admin badge/alert polling so requests remain on the origin currently serving the admin UI.

## 4.6.53 QA — 2026-09-15
- Adds explicit Up/Down controls for menu items so sibling order can be changed reliably without changing submenu parentage.
- Disables Up on the first sibling and Down on the last sibling.
- Retains drag/drop for hierarchy changes and all 4.6.52 navigation fixes.

## 4.6.53 QA navigation audience refinement
- Fix site-local custom Navigation URLs so root-relative links such as `/news`, `/events`, `/shop`, and `/admin.php` resolve under the configured DivisionDesk base path instead of the domain root, while avoiding double-prefixing already resolved URLs.
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.53 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Module

DivisionDesk Storefront 2.5.8

development · published · 2026-09-16T02:48:44+00:00

Full package changelog
# Storefront v2.5.8

- Removed only the public shop hero section (`sf-hero`) from the Storefront shop renderer for mobile/LCP performance testing.
- Preserves the trust strip, category section, product controls/grid, cart, checkout, product pages, settings, and all commerce behavior.
- No schema, migration, database, entitlement, Finance, or Membership changes.

# Storefront v2.5.7

- Fixed Storefront administration on current Core by using `RoleManager::can()` / `RoleManager::requirePermission()` for runtime authorization.
- Retains a guarded compatibility fallback for older Core builds that exposed `Capability::can()` / `Capability::require()`.
- Finance remains the required commerce/payment authority, but Storefront administration and catalog management do not require a configured merchant account merely to load.

# Storefront v2.5.6

- Fixed Storefront refunds by using Finance 1.2.6's stable source-refund API.
- Full remaining Storefront refunds now also return the remaining Finance convenience fee to the payer.
- Full order refunds restore tracked inventory exactly once.
- Cart and checkout now disclose Subtotal, Shipping, Convenience Fee, and Total before payment; discount/tax rows appear when applicable.
- Checkout totals update when the shopper switches between Standard Shipping and Local Pickup.
- Storefront stores the verified Finance convenience-fee amount after payment for order/report visibility.

# Storefront 2.5.5

- Fixed Finance 1.2.x checkout contract: Storefront now supplies explicit `fund_id`, `account_id`, and allocation line IDs.
- Added Storefront Settings selectors for active Finance Fund and Store Sales Income Account via Finance's stable public integration API.
- Checkout now fails early with a Storefront-specific configuration message instead of Finance's generic missing-account error.
- No direct Finance-table access was added to Storefront.

# Changelog

## 2.5.4 — 2026-08-30
- Identifies and addresses the live "no changes taking effect" condition as stale addon OPcache bytecode.
- Adds a brand-new migration that executes before Update.php / Addon.php and force-invalidates every Storefront PHP file in OPcache.
- This directly compensates for Core 4.4.4's module installer replacing addon files without addon OPcache invalidation, while the Core updater already invalidates Core PHP files.
- Adds live runtime markers so the loaded Storefront code can be verified conclusively instead of inferred from the package version card.
- No Storefront 2.6.x bump; patch remains on the user-mandated 2.5.x line.


## 2.5.4 — 2026-08-30
- Full Storefront stabilization pass; no incremental test builds are being delivered between 2.4.0 and this package.
- Moves the critical Core registration path into a minimal `Registration` class loaded directly by root Addon.php.
- Registers Website → Content → Storefront, six public components, and six public pages before any optional integration can run.
- Public component renderer now points to the always-loaded Registration class, eliminating custom-autoloader dependency from Core page rendering.
- Optional setup, widgets, search, Finance event listener, Smart Actions, jobs, dashboard, help and capability refresh are isolated so they cannot make the module disappear.
- Adds explicit deterministic Runtime loading for the complete Storefront codebase.
- Reprovisions only Storefront-owned module pages in migration 120 before registration; Core `/store` remains untouched.
- Fixes Finance completion reconciliation request key on the public order page.
- Retains the approved navy/gold Storefront visual system and all catalog/cart/checkout/admin functionality.


## 2.5.4 — 2026-08-30
- Full Core 4.4.4 contract rebuild using the actual uploaded Core source, Developer Platform 1.1.1, Publishing 1.0.5, and Rosters 1.3.5.
- Corrects Storefront administration registration to the exact working Publishing pattern: moduleAdmin('main') plus Registry::admin() under Website / Content.
- Corrects module component registration to Core 4.4.4's actual Registry::component(string,array) contract with `renderer` = `Class::method`.
- Corrects public module-page keys to local keys (`shop`, `product`, etc.) and keeps fully-qualified component IDs.
- Corrects the Store parent navigation key to `storefront:storefront.shop`, matching Rosters' working nested-page contract.
- Moves stale Storefront system-page cleanup into a real Core ModuleMigration so it executes before Addon::register().
- Preserves Core's required `/store` page unconditionally.
- Corrects Update lifecycle method to `Update::update()`.
- Corrects Core CSRF and capability calls to `Csrf::verify()` and `Capability::can/require()`.
- Corrects admin handler, dashboard, widget, event-listener, search-provider, scheduler and setup-wizard signatures.
- Corrects Membership Manager integration to current Addons\Rosters\MemberSession / MemberRepository / DuesCalculator APIs.


## 2.5.4 — 2026-08-30
- Fixes `SQLSTATE[23000] UNIQUE constraint failed: pages.slug` during upgrades from rejected Storefront builds.
- Moves stale-page reconciliation before all new public module-page registration.
- Uses supported Core page cleanup APIs first when available.
- Adds schema-aware direct cleanup fallback that deletes only rows whose Storefront ownership can be proven.
- Reconciles canonical `/shop*` and historical `store-product` / `store-category` Storefront rows.
- Explicitly and permanently excludes Core `/store` from every cleanup path.
- Adds duplicate-slug, DB-fallback, unrelated-user-page, and Core `/store` preservation regression harnesses.


## 2.5.4 — 2026-08-30
- Aligns Storefront with the package-qualified Core component/page IDs documented by working Publishing 1.0.5.
- Keeps callable component registration and `/shop` public root.
- Explicitly preserves Core's required `/store`.
- Adds best-effort cleanup of obsolete Storefront-owned page IDs only through a Core-exposed page cleanup API.
- Reasserts Website / Content / Novice admin placement and module-admin dispatcher/search metadata.


## 2.5.4 — 2026-08-30
- Fixes live admin discovery/navigation and unavailable public component issues after 2.3.1 installed successfully.
- Uses Core ownership-local registration IDs instead of pre-qualified `storefront.*` IDs.
- Registers public module components as callables, matching the active Core component contract.
- Adds signature-aware compatibility for array-metadata and three-argument component registries.
- Moves the public storefront from `/store` to `/shop` because `/store` is reserved by Core for the package Store.
- Adds `page=main` to the standard module-admin dispatcher URL and supplies Website / Content navigation/search metadata.
- Changes Storefront-owned cart/checkout/order slugs to `/shop-cart`, `/shop-checkout`, and `/shop-order` to avoid generic Core/module route collisions.


## 2.5.4 — 2026-08-30
- Corrects the live Core 4.4.4 `Module page requires component.` install failure.
- Registers six Storefront module components before registering their six Core public module pages.
- Public page descriptors now use the required `component` field instead of incorrectly using `handler`.
- Adds an exact regression harness that rejects a page lacking `component` and rejects a page that references an unavailable component.
- Adds compatibility coverage for Core builds exposing the component registry as `component()` rather than `moduleComponent()`.
- Retains the 2.3.0 full commerce/security/migration fixes.


## 2.5.4 — 2026-08-30
- Full corrective audit after live Core 4.4.4 exposed the invalid Registry bulk capability call.
- Removed the nonexistent bulk capability-registration API and rebuilt the live regression harness without it.
- Fixed checkout RecoveryService namespace fatal, server-side repricing/revalidation, shipping-method/address enforcement, Finance handoff cart preservation, exact-once Finance completion, cumulative refunds, tracked-inventory handling, fail-closed auth/CSRF, manual-order inventory, cart maintenance, category cycles and input/URL validation.
- Added refunded-cents upgrade accounting and expanded the release gate to 39 PASS / 0 FAIL.
- Retains Core-owned Store/Category/Product/Cart/Checkout/Order pages, admin/search, Finance 1.2.3 boundary, membership restrictions, persistent carts, layouts and approved public visual structure.


## 2.3.0 — 2026-08-29
- Rebuilt Storefront registration around the current Core 4.4.4 ownership lifecycle.
- Root class is exactly `Addons\\Storefront\\Addon`; `Register.php` is passive and never eagerly registers.
- Uses current `App\\Core\\Registry::moduleAdmin()` with required title/handler/capability and `Registry::modulePage()` for Core-owned Store pages.
- Uses `App\\Core\\Database::connection()` and `App\\Core\\Url::to()` so subdirectory installations work correctly.
- Removed guessed universal/split registry discovery, direct package API routing, and direct package asset URL assumptions.
- Added MySQL/SQLite-aware schema self-healing for fresh installs and upgrades while retaining Storefront data.
- Retains categories, variants, images, product layouts, member restrictions/member pricing, persistent carts, Save for Later, coupons, Finance checkout, merchant fee policy, order fulfillment/tracking/refunds, digital downloads, promotions, reports, receipts and fulfillment notifications.
- Fixed persistent-cart token reuse, variant inventory/price enforcement, and cross-engine inventory decrement SQL.
- Added current-Core lifecycle/registration regression testing and subdirectory URL assertions.
- All prior 2.1.x artifacts are rejected test builds and should not be promoted.
Core

DivisionDesk Core 4.6.55

development · published · 2026-09-16T00:31:05+00:00

Combines public Core, renderer, and active-theme CSS into one cached versioned response; improves member-auth language, SEO metadata, and text contrast without changing pages or navigation.

Full package changelog
# DivisionDesk Core Changelog

## 4.6.55 — 2026-09-15

### Improved
- Public pages now load Core, renderer, and active-theme CSS through one versioned, cached `site-css.php` response, preserving cascade order while reducing render-blocking stylesheet requests.
- Member login and verification documents now declare English language metadata and a meta description.
- Member authentication helper/brand text contrast was strengthened for WCAG AA readability.

## 4.6.54 QA
- Preserve administrator navigation parent/order/label choices across registry synchronization; suggested placement now applies only when a registry destination is first provisioned.
- Exclude wildcard `*` from navigation audience capability choices.
- Normalize www/non-www aliases for high-frequency admin badge/alert polling so requests remain on the origin currently serving the admin UI.

## 4.6.53 QA — 2026-09-15
- Adds explicit Up/Down controls for menu items so sibling order can be changed reliably without changing submenu parentage.
- Disables Up on the first sibling and Down on the last sibling.
- Retains drag/drop for hierarchy changes and all 4.6.52 navigation fixes.

## 4.6.53 QA navigation audience refinement
- Fix site-local custom Navigation URLs so root-relative links such as `/news`, `/events`, `/shop`, and `/admin.php` resolve under the configured DivisionDesk base path instead of the domain root, while avoiding double-prefixing already resolved URLs.
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.53 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Theme

Georgia Division Signature 3.4.3

development · published · 2026-09-16T00:31:02+00:00

Accessibility refinement: camp detail kicker and publishing metadata colors now meet stronger contrast targets. Existing pages, navigation, and customized/uploaded site files remain untouched; packaged assets still seed only when missing.

Theme

Georgia Division Signature 3.4.2

development · published · 2026-09-15T18:55:22+00:00

Hard customization-preservation rule: packaged theme assets seed only when missing and never overwrite existing site files. Administrator/custom replacements always win.

Module

Georgia Camp Directory 0.3.5

development · published · 2026-09-15T08:21:50+00:00

Fixes state scoping when DivisionDesk stores the organization state as a full name (for example Georgia) instead of its two-letter code; preserves nearest-camp search, ZIP/city resolution, ZIP maintenance tools, and ancestor search page.

Module

Georgia Camp Directory 0.3.3

development · published · 2026-09-15T08:14:38+00:00

Fixes Camp Directory public renderer PDO namespace resolution; retains state-independent nearest-camp search, on-demand ZIP/city resolution, ZIP maintenance tools, and ancestor search page.

Module

Georgia Camp Directory 0.3.2

development · published · 2026-09-15T08:05:17+00:00

Removes the national ZIP/ZCTA bulk download; resolves ZIP searches on demand; adds Fill Missing ZIP Codes using normalized addresses with Census coordinate/ZCTA fallback; adds safe removal of legacy cached ZIP/ZCTA rows; retains the georgia-camp-directory slug and state-independent behavior.

Module

Georgia Camp Directory 0.3.1

development · published · 2026-09-15T08:00:01+00:00

Removes the national ZIP/ZCTA bulk download; resolves ZIP searches on demand; adds Fill Missing ZIP Codes using normalized addresses with Census coordinate/ZCTA fallback; adds safe removal of legacy cached ZIP/ZCTA rows; retains the georgia-camp-directory slug and state-independent behavior.

Module

Georgia Camp Directory 0.3.0

development · published · 2026-09-15T07:36:29+00:00

Generalizes the module for any state while retaining the georgia-camp-directory slug; adds a module-owned /ancestor-search page; makes city/ZIP/address/current-location searches geographic with a 50-mile radius and nearest-first results; changes ZIP/ZCTA sync to national Census data.

Module

Georgia Camp Directory 0.2.0

development · published · 2026-09-15T07:17:46+00:00

Adds current-location, ZIP/city/address nearest-camp search; uses existing scv_camps latitude/longitude; adds official Census ZCTA sync/geocoding tools; polishes camp detail pages; adds ancestor-search component for the Georgia Genealogy page.

Core

DivisionDesk Core 4.6.53

development · published · 2026-09-15T06:51:31+00:00

Adds deterministic Up/Down sibling ordering controls in Navigation Manager with boundary buttons disabled; retains 4.6.52 navigation audience, capability, routing, and subdirectory fixes.

Full package changelog
## 4.6.53 QA — 2026-09-15
- Adds explicit Up/Down controls for menu items so sibling order can be changed reliably without changing submenu parentage.
- Disables Up on the first sibling and Down on the last sibling.
- Retains drag/drop for hierarchy changes and all 4.6.52 navigation fixes.

## 4.6.53 QA navigation audience refinement
- Fix site-local custom Navigation URLs so root-relative links such as `/news`, `/events`, `/shop`, and `/admin.php` resolve under the configured DivisionDesk base path instead of the domain root, while avoiding double-prefixing already resolved URLs.
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.53 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Core

DivisionDesk Core 4.6.52

development · published · 2026-09-15T06:36:42+00:00

Fixes Navigation Manager capability discovery and reliable before/after reordering within submenus; retains navigation audiences, canonical logout routing, and Core destination fixes.

Full package changelog
## 4.6.52 QA navigation audience refinement
- Fix site-local custom Navigation URLs so root-relative links such as `/news`, `/events`, `/shop`, and `/admin.php` resolve under the configured DivisionDesk base path instead of the domain root, while avoiding double-prefixing already resolved URLs.
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.52 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Core

DivisionDesk Core 4.6.51

development · published · 2026-09-15T06:29:26+00:00

Fixes Navigation Manager capability discovery and reliable before/after reordering within submenus; retains navigation audiences, canonical logout routing, and Core destination fixes.

Full package changelog
## 4.6.51 QA navigation audience refinement
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.51 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Core

DivisionDesk Core 4.6.50

development · published · 2026-09-15T06:13:42+00:00

Adds server-side navigation audience controls (everyone, logged-in members, or required capability), canonicalizes legacy member logout links through /logout, and restores Core-owned Home/About destination resolution in Navigation Manager. Includes the existing 4.6.50 navigation-save, logout-routing, and Pages trash-icon fixes.

Full package changelog
## 4.6.50 QA navigation audience refinement
- Added server-side per-menu audience rules: everyone, authenticated members, or a required capability.
- Navigation Manager can assign capabilities such as `admin.access` to custom or registry items.
- Canonicalized legacy member logout destinations to `/logout`.
- Core Home/About destinations now resolve correctly inside Navigation Manager.

# DivisionDesk Core 4.6.50 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Theme

Georgia Division Signature 3.4.1

development · published · 2026-09-14T22:11:11+00:00

Performance-focused 3.4.0 removes embedded base64 images from CSS, packages local assets, fixes Events widget namespacing, tightens Storefront, refines Publishing/Camps, preserves registry-owned member navigation and adds accessible responsive hero presentation.

Site Template

Georgia Division SCV Signature Site 3.4.1

development · published · 2026-09-14T22:11:06+00:00

Performance/polish update: removes hero carousel dot controls and resolves packaged hero images against the configured site URL so subdirectory installs do not generate domain-root 404s.

Module

Communications 1.4.24

development · published · 2026-09-14T22:11:04+00:00

Fixes staff-alert polling for authenticated members with administrative roles by using Core unified-principal authentication while retaining communications.inbox permission enforcement.

Full package changelog
# Communications 1.4.24 — Initial chat hydration performance

## 1.4.24
- Removed the unconditional browser GET to `communications-chat.php?after=0&read=0` during initial public-page load.
- Returning visitors with an existing live-chat cookie are hydrated server-side while the page is generated.
- Visitors without an existing chat cookie start with an empty client state and do not call the chat endpoint until chat is opened/used.
- Existing later chat requests, SSE, long-poll fallback, unread handling, and send behavior remain unchanged.

# Communications 1.4.23 — Member-admin alert authentication

- Staff alert badge/count endpoint now accepts Core unified authenticated principals, so a signed-in member with an assigned administrative role is not incorrectly returned 401 merely because they are not using a separate admin-account login. Permission enforcement remains `communications.inbox`.

## 1.4.23
- Newsletter subscriber audiences can target any active Core newsletter list; recipients are resolved at send time so scheduled and recurring campaigns honor current opt-ins/opt-outs.
- Campaigns now excludes `status=system` transactional/module-generated notification records from the user campaign workspace while preserving their deliveries and analytics.
- Added true recurring campaigns: daily, weekly, monthly by day-of-month or ordinal weekday, and yearly schedules with optional start date and end-by-date/end-after-count controls.
- Recurring campaigns create an immutable child run for each occurrence; recipients are resolved when the run is due, each run retains its own delivery history, and the parent campaign rolls email engagement up across runs.
- Added recurring campaign pause/resume/edit/reuse actions and clear next-send/run-count display. A recurrence that fails preflight is automatically paused rather than generating repeated failed runs every scheduler pass.
- Improved Campaigns visual hierarchy with consistent inline SVG navigation/channel/action icons, compact icon actions, schedule badges, and clearer scheduled/recurring filtering.
- Added send-time `{{communications.upcoming_events}}` dynamic content. The composer has a calendar insert control; published future Core Events are rendered when the email actually sends, so recurring event digests stay current without rebuilding the campaign.
- Campaign performance now exposes per-occurrence run history for recurring campaigns while retaining parent-level rolled-up open/click analytics. Added explicit End recurrence alongside Pause/Resume.

## 1.4.20
- Added Reuse for every saved campaign. Reuse copies campaign content, audience, channels and topic into a new unsaved campaign while deliberately excluding delivery history, analytics, status, approval and schedule.
- Added Edit for draft, scheduled and pending-approval campaigns; sent/queued history remains immutable.
- Reuse/Edit are permission-gated by `communications.compose`.

## 1.4.18 — 2026-09-09
- Redesigned Communications navigation with a dedicated module sidebar for faster access to Campaigns, Inbox, Templates, Deliverability, Providers, Live Chat, Staff Alerts and Status.
- Reorganized the Campaigns screen around a dashboard-first workflow: summary cards and campaign history appear first; **New Campaign** opens the composer only when needed.
- Added campaign status tabs and live search without changing campaign persistence, delivery, scheduling or approval behavior.
- Added per-campaign email engagement summaries directly in Campaigns: unique opens, total opens, open rate, unique clicks, total clicks and click rate.
- Added a campaign performance modal with deliveries, email deliveries, failures and engagement metrics.
- Campaign engagement reads the existing Communications tracking data that already feeds Core Analytics; no second tracking pipeline was introduced. Unique counts remain first-observed-per-delivery, while total counts include repeat tracking observations.
- Preserves all 1.4.17 delivery, transactional attachment, open/click tracking and Analytics event behavior.

## 1.4.17 — 2026-09-08
- Preserves existing first/unique `communications.email.opened` and `communications.email.clicked` analytics events.
- Records every valid tracking request as `communications.email.open_observed` / `communications.email.click_observed` so repeat engagement can be reported without inflating unique open/click rates.
- Provider tracking events are recorded on every valid request for short-term diagnostics; normalized Core Analytics remains the long-term reporting store.
- Adds a read-only email campaign/delivery directory method used by Core Analytics for campaign and recipient labels.
- Retains 1.4.16 attachment-capable transactional email delivery unchanged.

## 1.4.14 — 2026-09-04
- Added **Send Now (Don’t Save)** for one-off broadcasts that should be delivered and tracked without creating a saved campaign record.
- Added Delete actions for old campaigns. Completed delivery history is retained for analytics while pending delivery work is cancelled safely.
- **Save & Send Now** and draft **Send** now start a small immediate delivery batch in the web request instead of waiting entirely on the next scheduler interval; larger sends continue through Core's durable queue.
- Added a 60-second Communications queue-recovery job that recreates missing durable Core jobs for queued deliveries.
- Retains automatic parent campaign completion, open/click tracking, and the canonical tracked **Visit our website** footer link.
- Campaign actions update the Campaigns panel over AJAX without requiring a page refresh.

## 1.4.13
- Reworked the campaign composer around a clear normal workflow: Save Draft, Save & Schedule, or Save & Send Now.
- Moved Email Test, Preflight Analysis, and Full Deliverability Test into an optional Testing & Deliverability section so test utilities no longer look like the primary send workflow.
- Added in-place campaign-list refresh after save/schedule/send so newly saved campaigns appear immediately without a browser refresh.
- A saved draft now keeps its campaign ID in the composer; subsequent saves update that draft instead of inserting another campaign. A server-side submission token also makes duplicate AJAX/form submissions idempotent, preventing two rows even if the submit handler fires twice.
- Added a New Campaign action to deliberately clear the current saved draft and begin another campaign.
- Save & Send Now persists and queues the campaign in one action; Save & Schedule requires an explicit scheduled date/time. Approval-required campaigns are saved into the approval workflow rather than sent directly.

## 1.4.12
- Campaign status now advances from `queued` to `sent` after all deliveries complete, or `failed` after terminal delivery failure, instead of remaining permanently queued.
- Every tracked HTML email now receives a canonical `Visit our website` link immediately beside the open-tracking pixel; the link is routed through Communications click tracking.

## 1.4.11 — 2026-09-04

### Fixed
- Campaign test emails now create a Communications delivery record before MIME generation and receive the same signed per-delivery 1×1 open pixel and tracked links as bulk campaign deliveries.
- Bulk campaign tracking decoration now happens after the unsubscribe/footer HTML is assembled, so the final HTML MIME body contains the tracking pixel.
- `Tracking::decorateHtml()` now independently honors open-tracking and link-tracking flags instead of applying both whenever either was enabled.
- Test-send success/failure is recorded through Communications delivery/analytics events so real SMTP test messages can verify send → open → click behavior.

### Improved
- Campaign composer wording now clearly exposes `All active Membership Manager members in my scope` as the full scoped bulk-email audience and explains Camp, role, and manual targeting.

# Communications 1.4.10

- Preserves signed 1x1 open-pixel analytics for Communications email delivery.
- Adds independent open-pixel and link-tracking controls (`disable_open_tracking`, `disable_link_tracking`) while preserving `disable_tracking` as the master opt-out.
- Keeps first-open/first-click Analytics recording behavior unchanged.
- Core-owned email paths that bypass Communications still require the Core transactional-mail bridge and are not intercepted by this module alone.

# DivisionDesk Communications 1.4.9

- Added site-specific branding to every browser push notification.
- Push titles now include the configured Core site name rather than generic DivisionDesk branding.
- Uses the site's configured logo as the notification icon and favicon/logo as the badge when available.
- Preserves module-supplied images, icons, badges, and actions instead of overwriting them.
- Adds a default `Open` notification action when a destination URL exists and the browser/OS supports actions.
- Improved service-worker click handling for relative and subdirectory URLs.
- Retains all 1.4.2–1.4.8 concurrency, Campaigns, service-worker, VAPID, encryption, delivery, and URL-prefix fixes.

# DivisionDesk Communications 1.4.8

- Fixed browser-push links receiving the DivisionDesk installation prefix twice.
- Central push URL normalization is now idempotent: URLs already beginning with Core `basePath()` are preserved.
- Social Media alert URLs are no longer pre-expanded before the centralized normalization step.
- Retains all 1.4.2–1.4.7 performance, Campaigns, service-worker, VAPID, encryption, and push-delivery fixes.

# DivisionDesk Communications 1.4.7

- Fixed browser-push links dropping the DivisionDesk installation prefix on subdirectory sites.
- Centralized site-local push URL normalization through Core `Url::to()`.
- Social Media push alerts now explicitly normalize their inbox destination before delivery.
- Staff alert fallback links are also normalized through Core URL handling.
- Fully-qualified external URLs and special schemes remain unchanged.
- Retains all 1.4.2–1.4.6 performance, Campaigns, service-worker, VAPID, and Web Push delivery fixes.

# DivisionDesk Communications 1.4.6

- Fixed Web Push deliveries failing with `Undefined array key "urgency"` when a notification omitted an explicit urgency value.
- Social Media push alerts now explicitly use `urgency=normal` and a 24-hour TTL.
- Normalized ephemeral P-256 X/Y coordinates to exactly 32 bytes before Web Push payload encryption.
- Retains the 1.4.5 VAPID-key fix, 1.4.4 base-path service-worker fix, 1.4.3 Campaigns JS fix, and 1.4.2 concurrency fixes.

# DivisionDesk Communications 1.4.5

- Fixed Web Push enrollment failures caused by invalid-length VAPID P-256 keys.
- Generated EC X/Y coordinates and private scalar are now left-padded to exactly 32 bytes before base64url encoding.
- Push subscription discovery now validates the stored VAPID public key and returns a precise setup error if it is invalid.
- Retains the 1.4.4 service-worker base-path fix, 1.4.3 Campaigns JS fix, and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.4

- Fixed Web Push service-worker registration on installations hosted below the domain root.
- Push subscription discovery now uses Core `Url::to()` so the service worker resolves inside the active DivisionDesk installation, e.g. `/new_test_site/public/divisiondesk-push-sw.js`.
- Retains the 1.4.3 Campaigns JavaScript rendering fix and 1.4.2 polling/session-lock fixes.

# DivisionDesk Communications 1.4.3

- Fixed raw JavaScript appearing as visible text at the bottom of the Campaigns screen.
- Moved Campaigns UI JavaScript from a large inline heredoc to `communications-campaigns.js`.
- Public endpoint setup now deploys and validates that asset automatically.
- Retains Communications 1.4.2 lightweight polling/session-lock fixes.

# DivisionDesk Communications 1.4.2

- Generated high-frequency alert-count, chat, and inbox API endpoints now use Core lightweight bootstrap.
- These endpoints release the PHP session immediately and skip unrelated full add-on boot work, preventing long-poll/chat traffic from blocking normal admin pages.
- Works with Core 4.6.8 single-flight alert polling to prevent request pile-ups on shared hosting.

# Changelog

## 1.4.1
- Added normalized Core Analytics events for campaign queueing, notification queueing, delivery sent/delivered/failed/suppressed, email sent/opened/clicked/failed, live-chat start/inbound messages, and staff replies/internal notes.
- Email-open Analytics is explicitly low-confidence and click Analytics medium-confidence; member/campaign context is included when available.
- Added a Social Media alert event bridge: when Social push notifications are enabled, new external social comments/messages/mentions are pushed immediately to active admin Web Push subscriptions.
- Social push delivery does not create duplicate onsite alerts; Social Media remains the canonical global alert provider.

# Communications Changelog

## 1.4.0
- Replaced fixed chat polling with SSE-first transport and automatic long-poll/short-poll fallback for shared hosting.
- Added signed 1x1 email open tracking and safe HTTP(S) click tracking for Communications deliveries.
- Email opens/clicks now update delivery timestamps and Core Analytics signals.
- Preserved unread chat state when the widget is closed.

# DivisionDesk Communications Changelog

## 1.3.0 — 2026-08-15
### DivisionDesk notification-center integration
- Unread Communications staff alerts appear in the main DivisionDesk Administration notification bell.
- The bell is hidden when there are no unread alerts.
- Clicking a Communications alert marks that alert read and opens the exact related conversation.
- Communications registers its Web Push enrollment with Core so administrators are prompted at the top of Administration when browser notifications are available but not enabled on the current device.
- Existing Inbox unread badges, email alerts, push alerts and optional SMS staff alerts remain available.

## 1.2.5 — 2026-08-15
### Messaging usability
- Fixed the admin Inbox so long conversations scroll inside the message pane instead of expanding the whole page.
- Conversation list and current thread now own independent scroll regions.
- Reply composer remains anchored at the bottom of the current conversation.
- Mobile Inbox keeps a bounded scrollable conversation list and a dedicated thread viewport.
- Replaced the very short single-tone notification beep with a softer, longer two-tone chat chime.
- The improved notification sound is used consistently for new messages on both the staff Inbox and visitor chat.

## 1.2.4 — 2026-08-15
### Live messaging workflow
- Live chat requires the visitor's name and email address.
- A staff chat reply that remains unread for two minutes is emailed to the visitor; active visitors who read it in chat do not receive a duplicate email.
- Visitor name is now required before starting live chat so staff can distinguish conversations.
- Visitor chat persists across public-page navigation; an open chat reopens on the next page, while an intentionally closed chat remains closed.
- Visitor chat polls automatically and plays a short sound when a genuinely new staff reply arrives.
- Communications Inbox is now a two-pane live messaging workspace with all conversations visible beside the current thread.
- Conversation list and current thread refresh automatically without page reload.
- Admin receives a short sound when a genuinely new inbound message arrives.
- Replies, internal notes, status changes, assignments and conversation switching are fetch-driven.
- Conversation list shows visitor name, latest-message preview, channel, status and unread count.
- Open/pending, all, and resolved conversation views are available without overwhelming the default screen.

## 1.2.3 — 2026-08-15
### Staff message alerts
- New live chat, website-form and inbound SMS messages can notify staff automatically.
- Communications Inbox shows a live unread badge in DivisionDesk administration.
- On-site staff alerts link directly to the conversation.
- Email alerts are sent for new conversations by default; Advanced can email every inbound message.
- Browser push can be enabled independently on each staff device.
- Optional SMS alerts can be sent to configured staff numbers.
- Opening a conversation marks its associated staff alerts read.
- Staff Alerts settings save with fetch and include plain-language readiness/help.

## 1.2.2 — 2026-08-15
### Critical fix
- `communications-chat.php` and all other generated Communications public endpoints are now ensured whenever the module registers.
- Upgraded installations self-heal if an earlier update did not regenerate public endpoints.
- Removed suppressed writes from endpoint generation.
- Endpoint generation now fails loudly when `public/` is unavailable/unwritable or a generated file cannot be written.
- Final required-file verification runs before endpoint generation returns success.
- Existing generated files are rewritten only when contents differ.

### Regression tests
- Fresh endpoint generation.
- Upgrade simulation beginning from the pre-chat endpoint set.
- Missing-chat self-healing.
- Idempotent regeneration.
- Failure-path test proving an invalid public path no longer silently succeeds.

## 1.2.1 — 2026-08-15
### Critical upgrade fix
- Replaced the old single-table `Schema::ensure()` shortcut with a sequential migration ledger.
- Existing Communications installations now run every missing migration in natural version order instead of returning early when the original templates table already exists.
- Live-chat migration `003_live_chat.php` therefore runs correctly during module update, not only on fresh installs.
- Migration failures are transactional where supported and identify the exact migration that failed.
- Schema completion is checked after migrations.

### Packaging
- `addon.json` and `manifest.json` explicitly declare `package_type: module`.
- Version bumped to 1.2.1 so it cannot collide with the rejected/staged 1.2.0 package history.

## 1.2.0 — 2026-08-15
### Completed
- Site-wide live chat is automatically injected on public pages when Communications is enabled; no floating widget placement is required.
- Chat uses a speech-bubble icon, fetch-driven history/send/poll, secure guest session cookie, unread badge, mobile full-screen UI, office hours/away message, identity requirements, optional avatar/accent and path exclusions.
- Chat conversations and staff replies are fully integrated with the Communications Inbox.
- Contact/Message widget now provides Contact Card and fetch-driven Inline Form layouts; obsolete Floating Button layout removed.
- SMS provider validation now includes stored secrets; Providers includes real SMS test, segment count and administrator-configured approximate cost.
- Web Push VAPID key generation is exposed when the required runtime library is available.
- Reports include normalized provider callback outcomes.
- System Status page explicitly reports operational, configuration-required, dependency-required, disabled and unsupported-external-workflow states.

### Compatibility
- Requires DivisionDesk Core 3.6.4 for automatic public-page integration.
- Coordinated DivisionDesk Server 1.11.4 adds bounded independent DKIM verification and DMARC evaluation via aligned DKIM.

## 1.1.4 — 2026-08-14
### Fixed
- Full Deliverability create/status calls allow up to 20 seconds for bounded DivisionDesk Server analysis.
- Rebuilt directly from the publisher-validated Communications 1.1.2 package to eliminate staging ambiguity from the rejected 1.1.3 package.

## 1.1.2 — 2026-08-14
### Improved
- Deliverability modal now displays **Test Coverage** separately from Inbox Probability.
- Unavailable SpamAssassin and reputation checks are shown as `Not checked`/`Unable to check` rather than visually implying failure.
- Authentication shows evidence-aware states: Pass, Fail, Signature Present, Policy Present, or Unknown.
- Content & Links now includes a detailed reputation-query report showing provider, tested IP/domain, DNS response, interpretation and query.
- Reputation results distinguish **Clear**, **Listed**, and **Unable to Check**.
- Recommendations explain excluded/unavailable signals instead of treating them as negative delivery evidence.

## 1.1.1 — 2026-08-14
### Fixed
- Deliverability results now render as a true fixed overlay instead of appearing at the bottom of the Campaigns page.
- Mobile view becomes a full-screen sheet with scrollable details.
- Page scrolling is locked while the modal is open.
- Restored the `TestEmail::send(..., $options)` signature needed to attach the secure live-test correlation header.
- Live status displays mailbox-poll warnings instead of silently waiting forever.

## 1.1.0 — 2026-08-14
### Added
- Instant campaign Preflight Analysis.
- Full Deliverability Test through `mailtest@divisiondesk.com`.
- Secure DivisionDesk Server create/status test workflow.
- Actual campaign is sent through the site's configured SMTP transport with a correlation header.
- Responsive circular Inbox Probability gauge with gradual deep-red → red → orange → yellow → green progression.
- Large desktop modal becomes a full-screen mobile sheet.
- Live polling states: sending, waiting, received/analyzing, complete.
- SpamAssassin, authentication, blocklist, structure, content/link and recommendations tabs.
- Fetch-driven workflow; Campaign composer never reloads during testing.

### Changed
- Inbox Probability is explicitly presented as a DivisionDesk estimate, not a receiving-provider guarantee.

## 1.0.7 — 2026-08-14

### Fixed
- Fixed Campaign fetch actions returning Administration HTML before JSON.
- AJAX Campaign requests now authenticate/authorize without rendering `AdminUi::start()` first.
- CSRF verification is handled inside the JSON request error path.
- AJAX responses are explicitly JSON and `Cache-Control: no-store`.

### Diagnostics
- If a future fetch request receives non-JSON content, DivisionDesk shows a short excerpt of the actual HTTP response instead of directing the administrator to a server log that may contain no error.

## 1.0.6 — 2026-08-14

### Fixed
- Fixed `SMTP host and a valid envelope/From email are required` when Core has a valid From address but the optional envelope sender is blank.
- Empty `envelope_from` now correctly falls back to Core `from_email`.

### Changed
- Campaign **Send Email Test** and **Save Campaign** now use `fetch()` and display success/errors in place.
- Transport/validation errors no longer refresh the Campaigns page or clear the composer.
- Non-AJAX fallback restores posted campaign fields after a server-rendered error.
- Submit buttons show a busy state and duplicate submissions are prevented.

### UX direction
- Fetch/AJAX-style in-place actions are the preferred DivisionDesk interaction model where practical.
- User-entered form data should survive errors rather than returning to blank forms.

## 1.0.5 — 2026-08-14

### Fixed
- Fixed campaign test failure `List-Unsubscribe must be HTTPS or mailto.`
- Core relative/base-path URLs are no longer inserted directly into email headers.
- HTTPS web requests automatically establish a canonical DivisionDesk public site URL for Communications.
- Background campaign jobs reuse the stored canonical HTTPS site URL.
- Local/LAN/non-HTTPS installations fall back to a standards-valid `mailto:` List-Unsubscribe target instead of emitting an invalid relative URL.
- `List-Unsubscribe-Post: List-Unsubscribe=One-Click` remains limited to actual HTTPS unsubscribe endpoints.
- Avoids duplicating the Core base path when building absolute unsubscribe URLs.

### Diagnostics
- Communications Providers and Deliverability now show whether bulk email is using HTTPS one-click unsubscribe or the mailto fallback.

## 1.0.4 — 2026-08-14

### Fixed
- Communications now reads the existing DivisionDesk Core **Email Delivery** configuration for SMTP and From settings.
- Campaign Email Test no longer incorrectly reports SMTP as unconfigured when Core SMTP is already working.
- SMTP password is consumed from Core Mailer configuration; Communications no longer expects a duplicate `communications.smtp.password`.
- Blank EHLO/HELO remains blank in configuration and is resolved automatically by the mail transport at connection time.
- Campaign and queued email failures now identify the specific missing Core Email Delivery setting.

### Changed
- Communications → Providers no longer presents a second SMTP configuration form.
- The Providers page shows Core email readiness/status and links directly to the global Email Delivery page.
- Communications-owned provider settings are now limited to SMS and Web Push.

## 1.0.3 — 2026-08-14

### Fixed
- Fixed Campaigns buttons appearing to do nothing with Chrome error `An invalid form control with name='push_url' is not focusable`.
- Push URL, image, icon and badge fields now accept DivisionDesk template variables such as `{{site.url}}` without HTML5 URL validation blocking form submission.
- **Send Email Test** now uses `formnovalidate` so hidden/unrelated campaign channel fields cannot prevent a transport/template test from reaching PHP.

## 1.0.2 — 2026-08-14

### Fixed
- Built-in templates now self-heal if a previous installation or upgrade left `communications_templates` empty.
- Added upgrade migration 002 so 1.0.2 reliably invokes the idempotent template seeder after upgrading.
- Module registration, Campaigns, and Templates defensively restore missing built-ins without overwriting existing customized templates.
- Corrected Campaign list column rendering for topic, channels, schedule, deliveries and actions.

### Added
- Rebuilt Campaigns as a polished multi-channel composer.
- Template selection now immediately loads the template subject, styled HTML, plain-text version, SMS text and push payload into the composer.
- Rich HTML email editor with formatting controls and HTML-source toggle.
- Sandboxed email preview and push-notification preview.
- Immediate single-recipient SMTP campaign test using the production Communications email builder, including multipart HTML/text, Date, Message-ID, List-Unsubscribe and one-click unsubscribe headers.
- Improved channel cards/tabs, SMS character count, audience/timing controls and contextual deliverability guidance.
- Redesigned Template Library with cards, statistics, editor, and Restore Missing Built-ins control.
- Upgraded built-in Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Events, Dues Renewal, Welcome, Login Code, Application Status and Contact Response templates with polished inline email styling.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer; Core 3.6.1 is recommended.

## 1.0.1 — 2026-08-14

### Fixed
- Fixed fresh installation failure: `SQLSTATE[HY000]: General error: 1 no such table: communications_templates`.
- Communications now ensures its schema exists before seeding built-in templates.
- Install, enable and update entry points are safe against a partially completed 1.0.0 installation.
- Existing `CREATE TABLE IF NOT EXISTS` migration statements make recovery non-destructive.

### Compatibility
- Works with DivisionDesk Core 3.6.0 and newer.
- Core 3.6.1 separately corrects the generic module lifecycle ordering for all modules.

## 1.0.0 — 2026-08-14

### Added
- Multi-channel campaign model for Email, SMS, Push and on-site delivery.
- Membership Manager audience adapter with active-member, Camp and role targeting.
- Shared background delivery jobs using DivisionDesk Core 3.6 Job Queue.
- Multipart HTML/plain-text email construction with Date, Message-ID, Reply-To, List-ID, List-Unsubscribe and one-click unsubscribe headers where appropriate.
- Non-transactional email footer with physical/site address and unsubscribe link.
- Email header-injection safeguards.
- Deliverability Center with SMTP, sender, SPF and DMARC checks plus DKIM guidance.
- Suppression system for opt-outs, provider failures and invalid destinations.
- Built-in communication templates: Newsletter, Receipt, Donation Receipt, Announcement, Official Notice, Event Announcement, Event Reminder, Registration Confirmation, Dues Renewal, Welcome, Login Code, Application Status and Contact Response.
- SMS provider abstraction with Twilio, Amazon SNS and Telnyx outbound adapters.
- Normalized Twilio errors for invalid, landline/non-SMS, unreachable and opted-out numbers.
- Automatic permanent SMS suppression for selected permanent provider failures.
- STOP/START handling for inbound SMS.
- Incoming SMS webhook/conversation handling for Twilio and Telnyx.
- Standards-oriented Web Push subscription database and service worker.
- VAPID Web Push adapter integration point.
- Rich push payload model: title, body, URL, image, icon, badge, actions, tag, TTL, urgency and require-interaction.
- Unified Conversations Inbox for website/contact/SMS messages.
- Public Contact Us / Website Messaging system.
- Member Communication Preferences page.
- Contact, Announcement and Communication Preferences widgets.
- NotificationService API for other DivisionDesk modules to queue transactional or bulk notifications.
- Notification Rule trigger/action foundation.
- Provider settings using Core encrypted Secret Vault.
- Delivery reports, provider-event history and configurable retention foundation.

### Security
- Provider secrets are encrypted by Core 3.6 Secret Vault.
- Twilio webhook signatures are validated before incoming events are trusted.
- Telnyx Ed25519 webhook verification is supported when a public verification key is configured.
- Email header values reject CR/LF injection.

### Compatibility
- Requires DivisionDesk Core 3.6.0 or newer.
Core

DivisionDesk Core 4.6.49

development · published · 2026-09-14T22:10:58+00:00

Fixes Navigation Manager tree serialization under Core fetch-first POST handling, corrects member/admin logout destinations, and replaces textual page Trash actions with an accessible trash-can icon. Protected-page behavior is unchanged.

Full package changelog
# DivisionDesk Core 4.6.49 — Navigation Save and Logout Routing

- Fixed Navigation Manager order/nesting saves under Core's fetch-first POST layer. `tree_json` is now initialized immediately and synchronized after each drag operation, so the fetch capture layer cannot serialize an empty menu tree.
- Public logout now distinguishes a pure administrator login from a normal member login: administrators return to Administration login, members return to the public home page, and mixed/ambiguous sessions safely return home.
- Replaced the active Pages list's textual Trash action with an accessible trash-can icon while preserving all existing protected-page behavior.
- No protected-page lifecycle, registry ownership, or Navigation Manager rename/move/show-hide behavior changed.

# DivisionDesk Core 4.6.47 — Security Schema Verification Compatibility

- Fixes a false security-schema repair failure on managed MySQL/MariaDB hosts immediately after atomic `RENAME TABLE`.
- Unique-key verification now reads live table indexes with `SHOW INDEX` instead of relying on `information_schema.statistics`, which can be stale immediately after an atomic rename on some hosts.
- Index metadata parsing is tolerant of MySQL/MariaDB PDO column-name casing and preserves ordered composite-key verification.
- Security repair schema version advanced to 5 so affected installs re-verify using the corrected path.
- Retains the protected Core download transport fix and Mega Setup hierarchy fix from 4.6.46/4.6.45.

# DivisionDesk Core 4.6.46 — Protected Update Transport Compatibility

- Protected Core package downloads now prefer cURL, matching the working new-install transport and avoiding shared-host failures in PHP URL-stream handling.
- The stream fallback now captures HTTP status instead of collapsing every failure into a generic release-server error.
- Protected one-use download tokens are no longer echoed in updater exceptions.
- HTTP error responses from DivisionDesk Server surface the Server-provided explanation when available.
- Retains the 4.6.45 Mega Setup terminology fix and 4.6.44 fresh MySQL/MariaDB schema parity repair.

# DivisionDesk Core 4.6.45 — Mega Setup Terminology Compatibility Fix

- Fixed `public/mega-setup.php` calling removed `Terminology::all()` after the neutral hierarchy migration.
- Mega Setup now uses the supported `Terminology::mappings()` API.
- Retains the 4.6.44 fresh MySQL/MariaDB schema parity repair.
- Added regression coverage so Mega Setup cannot reference a nonexistent Terminology API again.

# DivisionDesk Core 4.6.44 — Fresh MySQL Install Schema Repair

- Restored MySQL/MariaDB schema parity for ten Core tables that already existed in the SQLite schema but were absent from `database/schema.sql`.
- Fresh MySQL installation now creates `site_settings` before `Settings::seedDefaults()` runs, fixing the setup failure `Table ... site_settings doesn't exist`.
- Also restores fresh-install definitions for Page Builder layouts/revisions, reusable sections, media folders/items, member role assignments, login codes, trusted logins, and menu locations.
- Adds a schema-parity regression so future releases fail QA if a Core table exists for SQLite but is omitted from MySQL.
- No licensing-enforcement behavior changed.

# DivisionDesk Core 4.6.43 — Licensing Enrollment UX

- Adds Settings → Licensing & Enrollment to the administration navigation.
- Core update failures involving licensing/signing keys now link directly to that screen.
- The existing explicit legacy-enrollment workflow remains deliberate; upgrades do not silently enable license enforcement.

# DivisionDesk Core 4.6.42 — Organization Unit Meeting Schedule Text

- Organization Units now treats `meeting_time` as a schedule string rather than an HTML clock-only value, allowing entries such as `2nd Tuesday at 7:00 PM`.
- The editor uses a normal text field with a recurrence-aware example.
- When the authoritative `scv_camps` provider is MySQL/MariaDB and `meeting_time` is a non-text type such as `TIME`, Core safely widens that existing column to `TEXT` before saving. SQLite already accepts text and requires no table migration.
- Core continues to use the existing `scv_camps` organization-unit source and does not create a competing table.
- Licensing, hierarchy semantics, and Store/Cubicle behavior are otherwise unchanged.

# DivisionDesk Core 4.6.41 — Protected Core Update Delivery

- Core updater now requests a signed, license/entitlement-validated one-use download token from DivisionDesk Server before any Core package bytes are transferred.
- Public release metadata remains readable for update discovery, but the updater no longer requires or consumes a public Core archive URL.
- Authorized package version, size, and SHA-256 are cross-checked against the public release manifest before extraction.
- Existing update backup, preflight, migration, rollback, and reporting behavior is preserved.

# DivisionDesk Core 4.6.40 — Mega Setup & Deployment Readiness

- Added a resumable Mega Setup Wizard for new installations while preserving opt-in behavior for existing upgraded sites.
- New installs defer optional entitled package downloads until the administrator chooses desired modules/features in Mega Setup.
- Added guided organization/hierarchy terminology, site-profile/branding, contact/social, timezone, and deployment-layout configuration.
- Added outbound SMTP configuration and test-mail readiness checks; deployment readiness requires a successful real mail test when outbound email is configured for production.
- Added entitlement-filtered module/theme selection and secure download/install using the existing RepositoryClient/package-security path rather than a parallel installer.
- Added entitled theme installation/activation, preview-image support, and site-template application with merge-by-default and explicit replace safeguards/backups.
- Added orchestration of package setup wizards through SetupWizardRegistry, including return-to-Mega-Setup flow; installed modules without a wizard require explicit administrator review, and failed module boots block readiness.
- Added deployment-readiness reporting that separates required actions, recommendations, and completed checks, including scheduler/cron guidance and Core-generated command information.
- Added contextual Learn More guidance for credentials that must be obtained from external providers.
- Added configurable deployment layouts with separate application root, public filesystem path, public URL, and URL base path; `/public`, cPanel `public_html`, and subfolder deployments are supported as distinct concepts.
- Added Website → Configuration → Move / Relocate with Prepare Move and Complete Move phases. Same-host path moves update deployment/base URL state after preflight; hostname changes require the existing licensing transfer/authorization path rather than silently rewriting licensed identity.
- Added first-login onboarding handoff after technical installation and preserved legacy-upgrade safety: existing installations are not forced into the new wizard.
- Retains all Core 4.6.39 neutral hierarchy contracts and compatibility aliases.

# DivisionDesk Core 4.6.39 — Neutral Hierarchy Migration

- Added neutral canonical hierarchy levels `level_1` through `level_4` with compatibility aliases for historical `national`, `division`, `brigade`, and `camp` keys.
- Added configurable singular/plural hierarchy terminology with SCV-compatible defaults.
- Added `OrganizationUnitDirectory`, a neutral Core facade over the existing authoritative `scv_camps` source; Core does not create a second Camp/unit table.
- Added Organization → Organization Units editor with add/edit/suspend/reactivate, contact, meeting/location, and repeatable social-link support when the provider exposes those columns.
- Added hierarchy terminology editor to Organization Units so terminology can be configured before the Mega Setup Wizard is completed.
- Added neutral `unit_code`, `unit_name`, `level_2_name`, and `level_3_name` aliases while preserving existing provider columns for module compatibility.
- Updated Core role/access/administrator/profile/import surfaces to render configured hierarchy terminology while preserving stable role, variable, import, and storage keys.
- Added neutral canonical role-level API while retaining the historical role-level API for existing modules.
- Restored the 4.6.38 technical installer unchanged; Mega Setup Wizard work is intentionally deferred to the next phase.

# DivisionDesk Core 4.6.38 — Licensing Enrollment, Cubicle & Attribution

- Added explicit licensing enrollment without changing upgrade behavior: existing installed sites remain `legacy_unenforced` until an administrator deliberately enrolls them.
- New installations now require DivisionDesk Server license/domain preflight in both browser and CLI installers before Core is downloaded/extracted, then cryptographic installation enrollment before the site database is created or `installed.lock` is written.
- Purchased module entitlements issued with a new license are handed to the existing RepositoryClient/Cubicle package installer after base Core setup, preserving the same dependency, signature, download-authorization, migration, and lifecycle path.
- Added persistent installation identity, Server-signed locally verifiable authorization certificates, runtime-domain validation, certificate refresh/transfer support, and neutral administrator recovery for enforced licensing failures.
- Added entitlement enforcement at Core/module/theme/widget-pack package boundaries while preserving package data; expired themes fall back to Core Basic and enrolled Core requires an active Core entitlement.
- Rebranded the software package Store experience as **Cubicle** while preserving `/store.php` route compatibility; enrolled clients use Server-authoritative visibility/entitlement state and protected download authorization.
- Added permission-controlled **Report a Problem** using the existing signed Server client-auth contract and diagnostic context.
- Changed Analytics Traffic Channels to preserve recognizable acquisition sources individually (Google, Bing, DuckDuckGo, Facebook, X, Instagram, Reddit, TikTok, paid search, Email, etc.) instead of collapsing search/social/email into broad buckets.
- Added licensing/certificate, legacy-safety, Cubicle-visibility, and Analytics attribution regression coverage.

# DivisionDesk Core 4.6.37 — Functional Navigation, Attribution & Import Center

- Reorganized Administration navigation by function: Settings pages from Core and installed modules collect under Settings, while reporting/analytics pages collect under Reports; operational module pages keep their declared Website/Organization/Modules destinations.
- Added explicit `nav_kind` support (`settings`, `reports`, `normal`, or `auto`) to the shared admin registry/module menu contract so packages can override conservative functional inference without changing routes or permissions.
- Expanded Analytics acquisition attribution with broad Traffic Channels (Campaign, Direct, Internal, Organic Search, Social, Referral, Other) while retaining granular Sources, referrers, and UTM fields.
- Expanded search/social referrer recognition and paid-click attribution for Google/Microsoft/TikTok/LinkedIn campaign identifiers without changing the Analytics schema.
- Added the shared Core Import Center for CSV/TSV staging, preview, field mapping, capability/CSRF enforcement, and package-extensible import targets via `Registry::importer()`.
- Added a built-in SCV Camp import target that writes to the existing SCV Operations `scv_camps` directory when present; Core does not create a competing Camp data store.
- Updated System Health telemetry testing to emit an explicit `TelemetrySelfTest` record/message so intentional probes are distinguishable from production errors while still exercising local, database, and Server delivery.
- Preserved the Server 1.22.9 telemetry contract; no Server-side change is required by this Core release.

# DivisionDesk Core 4.6.36 — Admin Navigation Grouping

- Refined the existing Administration mega-menu grouping without changing routes, permissions, screens, or admin functionality.
- Module admin entries now respect the functional destination explicitly declared by the module (`Website`, `Organization`, `Modules`, or `Reports`) instead of every module entry being forced into the Modules dropdown.
- Publishing/content integrations can therefore live with Website content, while operational modules such as Communications, Documents, Events, Membership, Finance, and SCV workflows can remain grouped under Organization when their package declares that destination.
- Reserved the Modules dropdown for package/module management and module pages that intentionally declare `Modules`; Core Store, Installed Modules, and Package Security now live together under its Packages section.
- Simplified the More dropdown into four coherent sections: Access & Accounts, Configuration, System & Maintenance, and Help & Diagnostics.
- Preserved the existing five top-level navigation destinations, Admin Modes, capability filtering, mega-menu behavior, search, alerts, and profile menu.

# DivisionDesk Core 4.6.35 — Builder/Public Responsive Parity

- Fixed breakpoint preview reflow so Desktop/Tablet/Mobile switching recalculates page-relative positioned blocks after the device frame finishes resizing; no element click is required to correct the preview.
- Added ResizeObserver/transition reflow hooks so asynchronously loaded widget previews and frame-size changes cannot leave stale geometry on the Builder canvas.
- Versioned the public renderer stylesheet to prevent stale cached CSS from making published widget Cards/List/Grid layouts differ from the Builder preview after Core upgrades.
- Hardened canonical widget card selectors for common widget wrapper/card class patterns and single-column mobile rendering.
- Reworked public page visual-boundary measurement to track both normal-flow section bottoms and actual absolute-positioned element bottoms, including late image/content size changes, so the footer remains below all page content.
- Added runtime resize/mutation/image-load remeasurement for page-positioned content while avoiding cumulative min-height growth.

# DivisionDesk Core 4.6.34 — Responsive Layout Engine & Builder Structure

- Added `Auto (recommended)` responsive behavior for Builder blocks. Desktop free positioning remains visually free; inherited free-position blocks return to safe document flow on Tablet/Mobile unless that breakpoint has an explicit layout override.
- Added responsive layout warnings on Tablet/Mobile for horizontal overflow and meaningful element overlap; the warning can select the first affected element.
- Preserved explicit Scale/Fixed behavior and per-breakpoint overrides for advanced designs.
- Made the selected-element contextual popover draggable via its grip so it can be moved away from obscured content.
- Added native Builder structure blocks for DIV, SPAN, UL, and OL with sanitized inline editing and public semantic rendering.
- Added canonical Core widget presentation wrappers for Cards, List, Grid, and Inline layouts, including responsive card grids and shared visual treatment.
- Directory-style widget presentation now reduces role-directory person names to First + Last while leaving underlying formal/member data unchanged.
- Retained Layers drag ordering, Lock/Unlock, z-order controls, floating shared Core WYSIWYG, page/footer containment, site styles, accessibility, widgets, templates, and legacy layout compatibility.

# DivisionDesk Core 4.6.33 — Floating WYSIWYG Toolbar

- Fixed the Visual Builder canonical Core WYSIWYG toolbar so it is truly out-of-flow and no longer consumes the left/sidebar or canvas layout space.
- Builder now requests the shared `App\Core\Editor::toolbar()` with a Builder-only CSS class and initial hidden state; the toolbar markup remains centralized in Core.
- The toolbar appears only while editing inline rich text, floats adjacent to the active editable element, and automatically moves below the selection when there is not enough room above it.
- The floating toolbar remains draggable; a manually dragged toolbar keeps the user-selected position for the current Builder session.
- Added safe optional `class` and `hidden` toolbar rendering options to the canonical Core Editor API without duplicating editor controls.

# DivisionDesk Core 4.6.32 — Responsive Canvas & Working Layers

- Reworked Builder free-position geometry after reviewing current Wix Studio, Webflow, Framer, and CSS responsive-layout guidance.
- New palette/asset drag drops are free-positioned at the drop point and use page-relative placement.
- New free-position elements store horizontal X and width proportionally (`%`) by default while retaining pixel vertical placement; existing 4.6.31 layouts without unit metadata remain pixel-compatible.
- Added explicit unit selectors for responsive geometry (`px`, `%`, `rem`, `em`, `vw`, `vh`) with per-breakpoint inheritance.
- Added a visible Flow/Free positioning state to each selected block toolbar.
- Rebuilt Layers rows with a visible drag grip, z-order, Lock/Unlock control, and an actions menu for Bring to Front, Bring Forward, Send Backward, and Send to Back.
- Layer drag/drop now updates stacking order consistently; the top layer is the front-most positioned object.
- Locked layers cannot be canvas-dragged, resized, or reordered until unlocked.
- Preserved page visual-boundary/footer containment for page-positioned content.
- Preserved Core shared WYSIWYG, theme/style inheritance, accessibility runtime, templates, widgets, and legacy Builder layout compatibility.

# DivisionDesk Core 4.6.31 — Builder Layering & Page Precision

- Added page-relative exact positioning as the default precision scope while retaining container-relative compatibility.
- Added real layer stacking controls: drag reorder, Bring Forward, Send Backward, displayed stack order, and per-layer Lock/Unlock.
- Locked elements cannot be accidentally dragged from the canvas or Layers panel.
- Public pages now measure page-positioned content and extend the page boundary so the footer remains below the lowest visual content.
- Builder canvas likewise expands to contain low-positioned exact content while preserving intentional blank space.
- Retained responsive breakpoint inheritance, shared Core WYSIWYG, themes/prebuilt styles, and accessibility behavior.

# DivisionDesk Core 4.6.31 — Builder Precision UX

- Exact placement is now immediately enabled from the block crosshair control; X/Y/Z controls appear first in Design and the selected element can be dragged directly.
- Exact-positioned elements support 1px arrow-key nudging and Shift+arrow/drag 10px steps.
- The contextual Design/Content inspector can be dragged anywhere and stays where the editor places it.
- The canonical shared WYSIWYG toolbar remains the same Core toolbar, but its Builder instance is now a movable floating surface.
- Existing responsive breakpoint inheritance, themes/site styles, structured layouts, and accessibility behavior are preserved.

# DivisionDesk Core 4.6.31

## Builder Studio — professional visual design foundation
- Rebuilt the Visual Builder workspace around first-class Add, Assets, Layers, Pages, Site Styles, and Components tools while preserving the existing structured page JSON, Page Layouts, reusable sections, complete Site Templates, shared Core WYSIWYG, module widgets/components, revisions, and trusted Code mode.
- Added breakpoint-aware design overrides for Desktop, Tablet, and Mobile. Tablet inherits Desktop until overridden; Mobile inherits Tablet/Desktop until overridden.
- Added precision positioning for Builder blocks with breakpoint-specific absolute X/Y coordinates, z-index, width, min-height, direct canvas dragging, direct resize handles, and Shift-assisted 10px snapping. Exact positioning can be returned to normal flow on any smaller breakpoint.
- Added responsive design controls for width, max-width, min-height, margin, padding, font size, background, text color, corner radius, shadow, section gap, section background image, and section padding.
- Public rendering now safely emits only allow-listed responsive design CSS values and preserves legacy visual-positioning behavior for existing pages.

## Assets / Media
- Promoted Core Media into a first-class Builder Assets workspace with search, Images/Video/Audio/Files filters, thumbnails, and drag-to-canvas behavior.
- Dragging an image creates an Image block, video creates a Video block, audio creates an Audio block, and a document creates a linked download/action button.
- Added hosted audio rendering and expanded Core Media uploads to common web video/audio and PowerPoint formats while retaining the existing upload size/security boundary.

## Site Styles and theme compatibility
- Added optional global Site Styles for brand colors, typography, content widths, and component radii. Blank values continue to inherit the active prebuilt theme; Site Styles are opt-in and do not replace theme packages.
- Existing theme styling remains authoritative unless an administrator explicitly sets a Site Style or per-element override.

## Accessibility
- Preserved the existing Core public Accessibility control unchanged.
- Added a Builder accessibility audit for missing image alt text, heading-order jumps, empty button text, and likely mobile overflow caused by exact positioning.
- Builder accessibility checks are advisory design-time safeguards; Core semantic rendering and public accessibility behavior remain the runtime contract.

## Builder usability
- Upgraded Layers into a selectable section/column/block tree.
- Added an in-Builder Pages navigator and richer reusable Components pane.
- Replaced text-heavy Builder chrome with compact icon-first actions where the action is recognizable, retaining labels/tooltips where needed for accessibility and clarity.
- Added Builder asset cache-busting for the 4.6.31 interface.

# DivisionDesk Core 4.6.27

- Centralized the canonical WYSIWYG toolbar in `App\Core\Editor::toolbar()`.
- Visual Builder now renders that shared Core toolbar instead of maintaining duplicate toolbar markup.
- Package editors using `App\Core\Editor::render()` therefore use the exact same Core toolbar source and inherit future Core editor changes sitewide.

# DivisionDesk Core 4.6.26

- Expands the existing Communications Analytics view; no parallel analytics store is introduced.
- Preserves `communications.email.opened` / `.clicked` as first-per-delivery unique signals so the existing Email Open Rate retains its meaning.
- Adds observed-open and observed-click reporting for repeat tracked requests, with campaign and recipient drill-down when Communications exposes its read-only reporting bridge.
- Adds hover/tap tooltips to Website Traffic charts showing date, Visits, Unique Visitors, and Page Views without changing traffic collection or counting.
- Retains all 4.6.25 security/data-integrity behavior unchanged.

# DivisionDesk Core 4.6.25

- Finalizes the Core 4.6 security/data-integrity release gate without changing the verified 4.6.24 runtime repair design.
- Retires stale regression assertions that contradicted the authoritative Membership Manager role-assignment architecture or hard-coded historical Core versions.
- Converts the superseded 4.6.22 destructive-repair regression into a guard that proves the unsafe repair path cannot return.
- Keeps the update-only atomic security-table rebuild, pre/post verification and rollback, update mutex, emergency OOM telemetry reserve, SQL-bounded Access Control reads, and Administrator compatibility grants.

# DivisionDesk Core 4.6.24

- Fixes legacy MySQL security repair when `roles.role_key` / `permissions.permission_key` are TEXT by normalizing staging columns to VARCHAR(190) before UNIQUE indexes are created. Live tables remain untouched until verified atomic swap.


- Supersedes the invalid 4.6.22 security repair path. Security-table repair is no longer executed from normal page bootstrap.
- Replaces multi-million-row duplicate DELETEs with a canonical-table rebuild and one atomic MySQL table swap, preserving the oldest logical role/permission IDs and effective role-permission relationships.
- Retains the old security tables until the replacement set passes verification and atomically restores the old set if post-swap verification fails.
- Adds a non-blocking Core update mutex so a manual update cannot race a concurrently running automatic update.
- Forces SecuritySeeder v4 and grants `*` to both historical Administrator role keys (`admin` and `organization_administrator`).
- Clears accumulated security-schema repair notices after a successful repair.

## 4.6.22 — 2026-09-06

- Replaces the silent legacy role/permission cleanup with a bounded MySQL security-schema repair that can safely remove millions of duplicate rows while preserving canonical role-permission relationships.
- Verifies and enforces UNIQUE keys for `roles.role_key`, `permissions.permission_key`, and `role_permissions(role_id,permission_id)` before marking the repair complete.
- Failed security-schema repair is now recorded through DivisionDesk error telemetry instead of being silently ignored.
- Legacy Core `admin` accounts now receive full `*` Administrator capability so the two historical Administrator role keys cannot produce contradictory access behavior; `organization_administrator` remains the Membership Manager mapping.
- Access Control labels the historical `admin` role as `Administrator (Core account)` and the roster-backed role as `Administrator (Organization)` to remove UI ambiguity.

## 4.6.21 — 2026-09-06
- Repairs legacy MySQL `roles`/`permissions` duplication while preserving canonical `role_permissions` relationships.
- Enforces UNIQUE keys on `role_key`, `permission_key`, and role/permission pairs.
- Makes Core capability/security seeding defensive even before schema repair.
- Access Control now groups permissions in SQL instead of loading an unbounded duplicate table into PHP memory.
- Keeps 4.6.20 local/Server telemetry diagnostics and reserves emergency memory so out-of-memory fatals can still be reported to DivisionDesk Server.

# Core 4.6.19

## 4.6.20 — Error telemetry hardening and access-control diagnostics
- Registers Core error handling immediately after the autoloader so configuration/session/bootstrap failures are captured instead of escaping before logging is active.
- Error logging destinations are now independent: local file logging, local `error_events` persistence, and DivisionDesk Server telemetry each run even if another destination fails.
- Technical 500 pages now show a unique error reference and truthfully state whether the report was saved locally and/or delivered to DivisionDesk Server.
- `ErrorReporter` now validates the actual HTTP status/JSON result instead of treating any response body (including HTTP errors) as successful telemetry.
- System Health now reports local error-log writability and the most recent telemetry-delivery result, plus a protected end-to-end telemetry self-test.
- Roles & Permissions now normalizes legacy/current role and permission display columns from `SELECT *`, catches/report its own data/render failures, and remains usable without assuming optional schema columns.

- Fixes RoleManager session refresh runtime bug (`array_map()` called with one argument) that could cause `access-control.php` and other permission-aware requests to return HTTP 500.
- Keeps administrator/account permissions additive with Membership Manager organizational roles.
- Adds regression coverage for RoleManager refresh syntax/runtime contract.

# Core 4.6.18
- Fixes the administrator/member-role permission bridge introduced during role-authority consolidation: administrator-account permissions and linked Membership Manager organizational roles are now additive rather than one overwriting the other.
- Refreshes effective roles after installed add-ons boot on each normal request, allowing newly assigned Administrator (`*`) access to take effect without depending on a stale session.
- Keeps any residual legacy Core member-role rows effective until Membership Manager has actually migrated them, so a failed/unmappable migration cannot silently remove access.
- Allows an installed role provider to link an administrator account to exactly one active roster member by email; ambiguous duplicate emails are not auto-linked.
- Hardens the Roles & Permissions page against older role-table schemas and fixes a defensive security-seeder grant edge case.

# Core 4.6.17

- Consolidates member-role assignment authority with Membership Manager 1.3.12+: when the roster provider advertises authoritative assignments, Core no longer merges legacy `member_role_assignments` rows into effective member permissions.
- Access → Member Roles becomes an informational handoff to Membership Manager instead of maintaining a competing assignment store once the authoritative roster provider is active.
- Keeps the legacy Core member-role path intact for installations without Membership Manager and during staged upgrades from older roster providers.
- Retains Core 4.6.16 access-page scaling/duplicate-display repairs and all 4.6.15 Analytics/timezone behavior.

# Core 4.6.16

- Repairs Access → Roles & Permissions so large or historically duplicated role catalogs no longer produce an oversized/failed page; only one selected role permission set is rendered at a time.
- Member Roles defensively collapses exact duplicate legacy role display rows while preserving existing assignments as recognized aliases.
- Adds `organization_administrator` as the full-control organizational Administrator access role using the existing `*` capability.
- Permission saves validate selected permission IDs, use duplicate-safe inserts, and consolidate duplicate legacy rows for the selected role key without changing unrelated roles.
- Retains all 4.6.15 Analytics/timezone and scheduler behavior unchanged.

# Core 4.6.15

- Analytics reporting dates now use the configured site timezone while UTC remains the canonical storage format.
- Custom ranges, Today/7 days/30 days/month/year presets, overview cards, communications metrics, sources, devices, referrers, landing pages, bot summaries, module metrics, and journey ranges all query the correct UTC boundaries for the selected local dates.
- Traffic-over-time day buckets are now grouped in site-local dates, fixing evening activity appearing on the following UTC day.
- Real-Time and journey timestamps are converted back to site-local time for display.
- Analytics date inputs retain native browser date controls and now open the native date picker from the date field where supported; the active site timezone is displayed beside the range controls.
- Acquisition/source classification is intentionally unchanged in this release.
- Retains the 4.6.14 durable job-queue scheduler fix unchanged.

# Core 4.6.14

- Background job queue reliability: every scheduler invocation now drains due persistent `core_jobs` work even when the normal 60-second scheduler interval was stamped moments earlier. This prevents queued Communications bulk-delivery jobs from being skipped while the CLI reports `nothing due`.
- The interval gate remains unchanged for ordinary recurring jobs; only the durable queue receives the due-work override.
- Add-ons are still booted before CLI tick, so package job handlers are registered before queued work is dispatched.

# Core 4.6.13
- Events Registration 2.1 authoritative pricing: new registrations no longer require attendee types.
- Supports event-level base registration fee and optional per-additional-guest registration fee.
- Quantity-choice add-ons permit blank per-item choices; Events UI is responsible for warning before submit.
- Historical attendee-type registrations remain readable.

## 4.6.11
- Events registration now validates/stores full primary-attendee address/contact data and member/camp details.
- Adds server-authoritative Guest Names, Quantity, and Quantity + Per-item Choice option semantics.
- Reducing a quantity discards values beyond the submitted quantity; stale hidden choices cannot affect totals.
- Numeric quantity options charge per unit and zero means no selection.
- Legacy duplicate `Registration Fee` options are ignored when the attendee type already has a base price.
- Retains 4.6.10 Events/Finance checkout and QR fixes.

## 4.6.10

- Corrects `config/version.php`, the canonical runtime version marker used by Core update verification.
- 4.6.9 accidentally left that file reporting 4.6.8, causing an otherwise-copied update to fail verification and roll back.
- Retains all 4.6.9 Events/Finance registration, pay-now/pay-later, QR/check-in and base-path URL fixes.

## 4.6.9
- Repairs Events payment handoff to current Finance.
- Adds pay-now/pay-later registration behavior without duplicating registrations.
- Fixes doubled base paths in Events confirmation/check-in links.
- Pending-balance registrations receive QR credentials and remain check-in eligible.
- Retains 4.6.8 polling/session-lock fixes.

# DivisionDesk Core Changelog

## 4.6.8
- Prevented overlapping/duplicate admin badge and alert pollers from accumulating slow requests.
- Added global poller guards, single-flight scheduling, and 8-second request timeouts.
- Added a read-and-close session bootstrap mode for read-only async endpoints so they do not hold the PHP session lock.
- `admin-alerts.php` now uses the read-and-close session mode while retaining full add-on registration.

## 4.6.7
- Carries forward the Core 4.6.6 transactional-email handoff and secure one-click member sign-in changes.
- Regenerated `release/core-files.json` against the exact 4.6.7 package contents so Server-side Core file verification matches the published version.

## 4.6.6
- Added `core:mail.transactional` event contract so Communications can own tracked transactional delivery when installed, with Core Mailer fallback.
- Member sign-in code emails now include a secure signed one-click link plus the six-digit manual fallback.
- One-click sign-in only succeeds in the browser session that initiated login, preventing mail-security scanners from consuming the login.

# DivisionDesk Core 4.6.5

## Performance and public-renderer quality
- Versioned Core static assets now receive long-lived immutable browser caching.
- Small active theme CSS is inlined; larger theme CSS is versioned with ETag/Last-Modified caching.
- Analytics browser confirmation is deferred until load/idle and sent once per analytics session/tab.
- Lightweight Analytics requests open PHP sessions read-only and release the session lock immediately.
- Shared Core scripts are versioned and deferred.
- Public pages now include a language attribute, a single main landmark, and a fallback meta description.
- Retains all Core 4.6.4 performance, 4.6.3 migration verification, and earlier stabilization fixes.

# DivisionDesk Core 4.6.4

## Performance stabilization
- Core security role/permission seeding is now version-gated instead of executing hundreds of SQL statements on every request.
- Public navigation registry synchronization is signature-cached and only re-runs when registered destinations or navigation edits change.
- Chat schema/default seeding no longer probes chat tables on every request once its schema version is current.
- Analytics browser-confirmation and heartbeat requests use a lightweight bootstrap and no longer initialize the full package/widget/application runtime.
- Retains all 4.6.3 cross-engine migration verification, 4.6.2 Analytics/chat/migration snapshot, and 4.6.1 release-stabilization fixes.

- Fixed SQLite → MySQL/MariaDB migration verification for tables with textual primary keys such as `site_settings`. Verification no longer depends on each engine's default collation/order.
- Text keys are now ordered bytewise (`COLLATE BINARY` on SQLite and `BINARY` on MySQL/MariaDB) before streaming fingerprints are compared.
- Tables without a primary key now receive deterministic all-column verification ordering instead of relying on physical/insertion order.
- Added canonical scalar comparison for integer, floating-point and decimal values so PDO/database type representation differences do not create false verification failures.
- Verification failures now identify row/key and column when possible while reporting only length/hash summaries for differing values, preventing sensitive setting contents from being exposed.
- Added Core 4.6.3 regression coverage for cross-engine ordering, canonicalization and safe diagnostics.

# DivisionDesk Core 4.6.2

- Database migration now freezes Analytics writes before refreshing the source snapshot row counts, preventing `analytics_events` from changing between preflight/copy/verification.
- Migration UI consumes the frozen snapshot counts returned after rollback protection is active.
- Non-empty destination databases now prompt for explicit destructive confirmation and can be emptied automatically before preflight.
- `communications-chat.php` is a hard page-view exclusion. Its requests may update session liveness only and never increment page views or engaged time.
- Historical Communications Chat page-view pollution is excluded from Overview, traffic series and Top Pages reporting.
- Analytics Top Pages now resolves human-readable page titles and links titles to the page in a new tab.
- Added Core 4.6.2 focused regression coverage for migration consistency, destination-empty UX, chat liveness/page-view exclusion and Top Pages presentation.

# DivisionDesk Core 4.6.1

- Fixed post-login Administration rendering where authentication forms could be intercepted by the generic fetch layer, causing the redirected admin page to load as fetch content instead of a full document and delaying `core.css` until refresh.
- Admin and member authentication/verification forms now use native browser document navigation; the fetch helper also excludes authentication endpoints defensively and promotes redirected non-JSON POST fetch responses to real top-level navigation so the authenticated shell/head assets always reload.
- Fixed member login completion redirecting to domain `/` instead of the configured DivisionDesk installation root on subdirectory installs. Safe member return paths are normalized through `Url::basePath()` / `Url::redirect()`.
- Added Administration **Member Roles** management with multi-role checkboxes and built-in Camp, Brigade and Division officer/access roles. Camp/Brigade/Division scope is inferred from the member hierarchy instead of requiring a duplicate scope selection.
- Core-managed member role assignments are now additive with roles supplied by Membership Manager/Rosters rather than being ignored when a roster role provider is active; Core roles can also be assigned locally before/without a roster provider.
- Added built-in roles for Camp Commander, Camp Adjutant, Camp Treasurer, Camp Webmaster, Brigade Commander, Lt. Brigade Commander, Division Commander, Division Adjutant, Lt. Division Commander, 2nd Lt. Division Commander, Division Webmaster, Division Treasurer, Division Communications Chairman, Division Events Manager, and Division Page Editor.
- Fixed Analytics page-view inflation: XHR/fetch/prefetch requests are excluded from document-view collection, and same-page document refreshes/tab-state reloads no longer increment logical page views within the same session.
- Expanded the Analytics Overview to more closely match the approved mockup, including the six-card KPI row, traffic-source donut, top pages, email/social/member engagement panels, top referrals, device breakdown and real-time overview.
- Added returning-member, email-bounce and unsubscribe summary signals to Analytics reporting.
- Fixed SQLite → MySQL/MariaDB migration error 1075 caused by treating every integer component of a composite SQLite primary key as `AUTO_INCREMENT`. Only a single integer primary key can now translate as auto-incrementing.
- Fixed failed database-transfer cleanup so a prepare-stage failure drops any partially-created destination tables; users can retry against the same empty destination after **Cancel Move & Clean Up**.
- Fixed SQLite partial UNIQUE index translation so a partial uniqueness rule is not broadened into an unconditional MySQL UNIQUE constraint during migration.
- Added Core 4.6.1 release-blocking regressions for authentication navigation, base-path redirects, Analytics logical-page counting, database schema translation/cleanup, multi-role management and the retained Storefront namespace parser fix.

# DivisionDesk Core 4.6.0

- Added full-page **Visual / Code** Page Builder mode for the complete editable page body.
- Added canonical DivisionDesk page-source markers so dynamic module/widget content remains dynamic in Code mode.
- Added trusted HTML/CSS/JavaScript/PHP page-source preservation; executable JavaScript/PHP requires the new `pages.code` capability.
- Trusted PHP is executed through a generated server-side page-code cache include rather than direct `eval()`, with runtime error isolation/logging.
- Added permission-driven authenticated principals: authenticated members can use Administration features when their roles grant the required capability, without a duplicate administrator password account.
- Added `AdminAuth::principal()` and `AdminAuth::requireAdminAccount()` while retaining capability checks through `RoleManager`.
- Added canonical reusable `Editor::render()` WYSIWYG entry point so modules such as Publishing can consume the Core editor without recreating Site Builder toolbar markup.
- Added Analytics 2.0 traffic quality: `human`, `likely_human`, `unknown`, `likely_bot`, and `bot`, with confidence scores and classification reasons.
- Added known crawler identification plus JavaScript browser confirmation and engagement evidence; lack of JavaScript alone is never treated as proof of a bot.
- Added human/bot/unknown/all traffic filters, previous-period comparisons, referrer/landing-page reports, bot summaries, cross-module activity, session journeys, and expanded Real-Time reporting.
- Expanded Analytics Center into Overview, Website, Communications, Social, Members, Organizations, Events, Finance, Content, and Real-Time views with styling aligned more closely to the approved dark Analytics mockup.
- Added `analytics.view` capability and updated Core 4.6 API/endpoint documentation.

# DivisionDesk Core 4.5.4

- Fixed Page Builder HTTP 500 / `Unexpected token '<'` failures when an installed package registers an editor profile before Core editor defaults are initialized.
- `EditorRegistry::boot()` now ensures each required Core profile (`page`, `publishing`, and `email`) exists individually instead of treating any pre-registered package profile as proof that Core boot completed.
- Unknown editor profiles now safely fall back to the guaranteed Core `page` profile without reading an undefined array key.
- Retains the 4.5.3 notification dismiss/Clear all controls and Builder script-safe serialization, plus the 4.5.2 SQLite concurrency and Analytics corrections.

# DivisionDesk Core 4.5.3

- Fixed Page Builder startup failures (`Unexpected token '<'`) when page, widget, or registered component data contains HTML capable of terminating an inline `<script>` block.
- Builder bootstrap JSON now uses script-safe hexadecimal escaping and substitutes invalid UTF-8 instead of emitting malformed startup JavaScript.
- Added an explicit dismiss control to every Administration notification.
- Added **Clear all** to mark all currently unread/dismissible notifications as read without opening each destination.
- Notification actions refresh the bell/count immediately after dismissal.

# DivisionDesk Core 4.5.2

- Fixed SQLite `database is locked` regressions exposed by Core Analytics under overlapping PHP requests.
- Added a 5-second SQLite busy timeout and WAL/NORMAL concurrency tuning with compatibility fallback.
- Deferred automatic public page-view persistence until request shutdown so payments, forms, navigation, and module business logic take priority over telemetry.
- Fixed Analytics IP-hash salt persistence: 4.5.0 stored the salt as non-autoload while reading through the autoload cache, causing an unnecessary `site_settings` write on every tracked request.
- Public navigation registry sync now updates menu rows only when parent, label, or order actually changed rather than issuing writes on every public page request.
- Analytics collection failures now use a file-only analytics log path so a telemetry lock cannot recursively create another database write through the Core error-event logger.

# DivisionDesk Core 4.5.0

- Added Core Unified Analytics 1.0 with durable first-party session/event storage.
- Added pseudonymous guest visitor/session tracking and authenticated member journeys.
- Added referral classification and UTM campaign attribution.
- Added measured cumulative session engagement heartbeats and real-time active-session reporting.
- Added the Analytics Center dashboard and authenticated reporting API.
- Added `Integration::analytics()` as the stable package-facing analytics SDK method.
- Added automatic EventBus signal capture with recursion protection and confidence metadata.
- Added Core mail send/failure analytics signals without storing message bodies or recipient addresses in analytics properties.
- Added Core 4.5.0 endpoint/API contracts and release QA documentation.
- Updated embedded Developer Platform integration documentation for Analytics.

# Changelog

## 4.4.6 — 2026-08-30
- Corrected `config/version.php` to 4.4.6; the Core updater verifies this file after copying the update.
- Carries forward the verified `Addons::declaredAddonClass()` namespace parser correction.
- Fixes valid addon namespaces ending in letters such as `n`, `r`, or `t` being truncated.
- `Addons\Storefront` now resolves correctly instead of being read as `Addons\Storefro`.
- Supersedes the previously published bad 4.4.5 artifact.

## 4.4.5 — 2026-08-30
- Fixed `App\Core\Addons::declaredAddonClass()` namespace parsing.
- The previous `trim()` mask could strip valid trailing namespace letters such as `n`, `r`, and `t`.
- `Addons\Storefront` is now preserved correctly instead of being misread as `Addons\Storefro`.
- No Storefront package workaround is required after this Core patch.

# DivisionDesk Core 4.4.4

- Added optional parent relationships for module-page navigation destinations.
- Navigation registry synchronization now creates destinations first, then resolves parent/child links, including already-installed auto-added destinations.
- Enables modules to expose cohesive public dropdown navigation while continuing to render through the active site theme/header/footer.
- Added safe MemberAuth methods for listing and revoking remembered member devices.
- No breaking Core API or database contract change.

# DivisionDesk Core 4.4.3

- Fixed member OTP completion failure when a roster provider omits `display_name`.
- Valid OTP codes are no longer consumed until member login completion succeeds.
- Preserved safe member return targets so `my-membership.php` authentication returns to the requested page.
- Versioned Core asset URLs so CSS/JS changes are not hidden by stale browser caches after upgrade.
- Organization navigation categories now render in one vertical collapsed stack instead of a two-column grid/horizontal-scroll layout.
- Retains the 4.4.2 UTC OTP expiration, immediate delivery, resend/cooldown, and editable email-template improvements.

# DivisionDesk Core 4.4.2

- Fixed member OTP expiration to use consistent UTC timestamps across PHP and SQLite/MySQL verification.
- Added reliable resend-code flow with cooldown and specific expired/incorrect/locked feedback.
- Member verification mail is sent synchronously through the configured transport and a failed send removes the unusable code.
- Added editable professional HTML/plain-text member sign-in templates under `templates/email/`.
- Redesigned Member Login, Verify Login, and My Account using shared Core admin UI styling.
- My Account now has distinct Profile, Password & Security, and Remembered Devices sections with responsive layouts.
- Organization navigation with more than three categories now collapses categories into expandable sections instead of presenting a long persistent scroll list.
- Preserves all Core 4.4.1 platform, Store, Builder, Chatroom, scheduler, setup-wizard, search, API/SDK, and package-security behavior.

# DivisionDesk Core 4.4.1

- Fixed a package-scheduler defect exposed by Social Media: `bin/scheduler.php` now boots installed modules and Widget Packs before `Scheduler::tick()`.
- Package recurring jobs, registered Smart Actions and job handlers are therefore available during the real CLI cron process.
- No Page Builder, Chatroom, Store, accessibility, setup-wizard, or other 4.4.0 feature was removed.

# DivisionDesk Core 4.4.0

## Chatrooms & Meeting Mode
- Added the first-party Core Chatroom service and Page Builder widget with multiple switchable rooms.
- Rooms support Public, Members Only, or Private access with explicit room members, moderators and room administrators.
- Added near-instant incremental conversation updates without full-page refresh or blinking.
- Added online presence, live Meeting Mode attendance, attendance corrections and meeting start/end records.
- Added smart inline detection for motions, seconds, vote requests/results, officer/committee reports and adjournment.
- Detected meeting actions render as contextual hyperlinks inside the conversation (for example, **Second this motion**) rather than a separate bank of parliamentary buttons.
- Added structured voting with per-attendee Aye/Nay/Abstain responses and deterministic vote closure/results.
- Added optional raw transcript and Smart Minutes generation including date/time, chair/start record, attendance, reports, motions, seconds, vote results and adjournment.
- Added Smart Answers for approved common questions, native/custom/animated emoji support, safe hyperlinks, SSRF-protected URL previews and image thumbnails.
- Added responsive desktop/tablet/mobile Chatroom UI matching the approved DivisionDesk Meeting Mode design target.

## Core release blockers corrected
- Package downloads now always carry the installed Core version and client key on every DivisionDesk Server download path, including fallback/cached catalog URLs; the same identity is also carried in request headers.
- Public newsletter signup no longer invokes an administrator-only Smart Action. Core stores the subscriber reliably and emits `newsletter.subscribed` for integrations.
- Newsletter storage now repairs older table shapes missing status/source/timestamp columns.
- Page Builder charts now honor the Show Labels setting visually and contain wide bar charts inside a responsive internal scroller instead of overflowing the page/container.
- Store lifecycle continues to show Uninstall alongside Update for installed modules/widgets/widget packs and inactive themes.

## Compatibility
- Built directly on the current Core 4.3.9 production tree. Existing Admin Search, setup wizard framework, scheduler, AJAX/fetch framework, accessibility controls, Builder/editor, Developer Platform, package trust and Store lifecycle contracts are retained.

# DivisionDesk Core 4.3.9

- Built directly from the complete 4.3.8 corrective tree, which itself is based on the uploaded 4.3.6 production Core.
- Package download errors now preserve useful plain-text Server response bodies as well as JSON errors, so HTTP 409 reports its actual cause.
- Retains the Store fallback trust/grant preservation and stale-cache invalidation introduced in 4.3.8.
- No module/theme/widget/widget-pack lifecycle functionality removed.

# DivisionDesk Core 4.3.8

## Production staging corrective release

- Reworked `bin/doctor.php` into conservative PHP 8.1 syntax after the production Server staging gate rejected the unchanged 4.3.6-era doctor file under the hosting lint environment.
- Preserves all Core 4.3.7 Store trust/fallback corrections and the complete 4.3.6 runtime baseline.
- No existing 4.3.6 runtime file is removed.

# DivisionDesk Core 4.3.7

## Production Store trust corrective release

Built directly from the complete DivisionDesk Core 4.3.6 release.

- Fixed the legacy/fallback Store catalog path so it preserves DivisionDesk Server-authoritative `server_trust`, `security_review_state`, `official`, `granted_permissions`, and nested trust metadata.
- This prevents an Official DivisionDesk package from being silently downgraded to Community immediately before `PackageValidator`, which caused false `DD-PKG-020` failures for reviewed providers such as `graph.facebook.com`.
- Kept the existing 4.3.6 security model intact: the package ZIP cannot self-award Official trust; trust is derived only from remote Store/Server metadata.
- Added Widget Pack coverage to fallback Store package reconstruction so 4.3.6 Widget Pack lifecycle support is not lost on fallback.
- Store catalog cache schema bumped to 2 so stale pre-fix thin catalog records are ignored.
- Package-download errors now preserve the Server's JSON error detail for HTTP 4xx/5xx responses instead of reducing every failure to a status number.
- Installed `.security.json` records the Server security-review state used during validation for diagnostics.
- No existing 4.3.6 module/theme/widget/widget-pack lifecycle, reinstall, uninstall, usage-preservation, builder, setup, scheduler, or admin contracts were removed.

# DivisionDesk Core 4.3.6

- Fixes Store lifecycle controls so installed modules, non-active themes, standalone widgets, and published widget-container packages can be reinstalled or uninstalled from the Store.
- Reinstall forces a fresh verified download of the same Store version without purging module data; required dependencies remain validated/installed first.
- Widget uninstall preserves Page Builder JSON and reusable sections, warns/asks for confirmation when the package is in use, and allows clean reinstall later.
- Recognizes Platform 1.0 `type: widget` packages whose `widget.json` / `manifest.json` contains `widgets[]` as containers: Core exposes each qualified child widget individually and never creates a pack-level pseudo-widget.
- Adds child-widget package security context so one container security record protects every child renderer.
- Preserves both typed `WidgetContext` and legacy `array $context` renderer callbacks.
- Translates package download HTTP 401/403 into an actionable license/entitlement message instead of exposing the raw download URL/client key.
- Keeps Platform 1.0 package/Store contracts backward-compatible.

# DivisionDesk Core 4.3.5

- Fixes direct WYSIWYG editing so editable text no longer reopens the legacy Content Block inspector; selection is preserved across toolbar interaction and font, size, bold/italic/underline, colors, highlights, alignment, lists, links and inline images persist through save/render sanitization.
- Makes empty canvas and open column space valid drag/drop targets with insertion-aware placement instead of requiring a pre-existing empty column.
- Renames and surfaces the native accessible `Chart / Graph` block in the element palette.
- Adds Upload & Select directly to the Builder Media picker and normalizes legacy `/uploads/...` URLs for subdirectory installations.
- Guarantees Core Setup Wizard Back / Save & Continue / Skip / Finish navigation with AJAX busy state and validation feedback even when a module only supplies fields/render callbacks.
- Makes desktop admin mega menus JS-controlled and single-open so adjacent menus cannot overlap; Escape/click-away closes them.
- Makes module-provided admin destinations Advanced by default unless the module explicitly chooses another minimum mode; mode still never grants permissions.
- Prevents duplicate/legacy addon slug identities such as `socialmedia` and `social-media` from reaching PHP class redeclaration: Core preflights installed rows/classes and the installer refuses colliding identities.
- Adds Media Library avatar selection/upload from My Account.
- Extends Builder/UI regression coverage for all above defects.

# DivisionDesk Core 4.3.3

- Hardens the shared public router so optional theme/navigation/page/widget/footer failures are isolated and reported instead of taking down every public page.
- Adds defensive handling for malformed legacy navigation/page metadata and a permanent public-runtime regression suite.
- Preserves Developer Platform 1.0 contracts and all 4.3.x backward compatibility.

# DivisionDesk Core 4.3.2

- Reworks Builder interaction around direct in-canvas editing and Builder-safe real widget/module previews.
- Preserves legacy widget callback signatures through a reflected compatibility adapter.
- Adds Core float-left/right text wrapping, width controls, and responsive stacking.
- Moves Admin Mode switching to the profile/avatar menu and makes Novice/Advanced/Webmaster materially filter interface complexity without changing authorization.
- Anchors mega menus to their trigger and constrains them to the viewport.
- Rebuilds dashboard first-run scheduler state as setup/onboarding and reclassifies missing package-schema job failures as package setup/update conditions.
- Keeps scheduler web fallback opt-in rather than silently running jobs on public requests.
- Updates Developer Platform 1.0 exact contracts without breaking package APIs.

# DivisionDesk Core 4.3.1

- Rebuilt the Visual Page Builder shell to match the approved direct-editing design: compact dark header, Pages → current-page breadcrumb, one floating WYSIWYG toolbar, dark grouped/collapsible scrollable element library, contextual block popovers, responsive preview dock, autosave state, Publish action, and Page Settings modal with SEO/social-sharing preview.
- Preserved existing version-1 Builder layout JSON and existing module/widget/component registration contracts.
- Replaced nested Administration flyouts with viewport-safe mega menus under a reduced top-level navigation set: Dashboard, Website, Organization, Modules, Reports, More.
- Improved live Administration search so Feature/Action results and Help/Documentation results are visually separated; fuzzy, phonetic, alias and synonym matching remain permission-filtered. Ctrl/Cmd+K focuses live search.
- Added first-run Scheduler Setup workflow. A scheduler that has never been seen is now onboarding/setup, not a 10-minute health failure. Only a previously healthy scheduler that becomes late raises a runtime warning.
- Scheduler errors caused by a missing package table are isolated as package setup/update warnings instead of generic red fatal notices; successful subsequent runs clear their prior notice.
- Added `/scheduler-setup.php` CSRF-protected setup/test actions and documented the exact request/response contract.
- Updated Help, Core endpoint inventory, Core API contracts, Platform contract tests and UI regression tests.

# DivisionDesk Core 4.2.9

- Fixed shared installed-module boot lifecycle so packages are registered once per request.
- Removed the redundant unprotected second `Addons::bootInstalled()` call from the public site router.
- Made `Addons::bootInstalled()` idempotent across public/admin/Builder/Help/search routes.
- Added per-package register failure isolation: a broken package is reported and skipped instead of taking down the entire client site.
- Failed package registration is attempted only once per request and surfaced through an Administration notice/error report.
- Added regression coverage proving a healthy module registers once and a deliberately broken module cannot escape the package boot boundary.

# DivisionDesk Core Changelog

## 4.2.9 — 2026-08-18

- Fixed a site-wide 500 failure triggered after installing modules: `bootstrap.php` already booted packages, while the public router booted them a second time outside the protected boundary.
- Installed module boot is now idempotent; successfully registered modules are never registered twice in the same request.
- Package `register()` failures are isolated per package, logged through Core error reporting, and surfaced as an administrator notice instead of aborting the public request.
- A package that fails initialization is not repeatedly retried during the same request.
- Public routing no longer redundantly calls `Addons::bootInstalled()` after bootstrap.
- This hardening also protects Builder, Help, Administration Search, Integration Actions, and other routes that may invoke the boot service more than once.
- Regression test: healthy module registers once across two boot calls; intentionally broken module throws once, is isolated, and does not propagate a fatal error.

## 4.2.7 — 2026-08-18

### Fixed
- Store protocol trust normalization now honors the Server-authoritative `server_trust` field as well as supported legacy trust fields. Official packages no longer fall back to Community during quarantine validation merely because Server used the current trust field name.
- Store catalog retrieval now merges all successful modern Server catalog endpoints instead of stopping after the first successful endpoint. This prevents a module-only endpoint from hiding Themes, Widgets, Site Templates, or Page Layouts exposed by another current catalog source.
- Store catalog requests now send the persistent client key, Core version, channel, and `runtime=client` so DivisionDesk Server can apply licensing/entitlement/runtime visibility consistently.
- Modern catalog data remains authoritative for trust, licensing, runtime, and permission metadata; legacy repository data may supplement missing download/checksum fields but cannot overwrite richer Server security metadata.
- Removed an accidental nested Core working-tree copy from the release tree and added release-root sanity checks.

### Added
- `bin/store-probe.php`, a non-secret diagnostic probe that queries the live Server catalog endpoints and reports response keys, package-family counts, trust/runtime/licensing fields, and normalized trust independently of the Store UI.

### Development rule
- Cross-component protocol awareness is a hard DivisionDesk release rule: Core, Server, modules, themes, widgets, templates and related packages must be reviewed against the latest shared contracts before release.

# DivisionDesk Core 4.2.5

- Fixed Store AJAX endpoint resolution when a form contains an input named `action`; the literal form action attribute is now used so requests cannot become `/[object HTMLInputElement]`.
- Store catalog extraction now merges flat and grouped package-family records so Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layouts can coexist in one Server response.
- Fixed Page Builder/WYSIWYG assets on subdirectory installs by using the configured DivisionDesk base path instead of root-relative `/assets/...` URLs.
- Added the shared fetch helper to the Visual Builder so Save/Apply operations use the standard spinner/busy-state behavior.
- Corrected related root-relative asset/navigation links in Media, Page settings, Navigation, Revisions, Roles, member login/verification, and setup-complete screens.
- Rebuilt Administration navigation for smaller screens with an explicit Menu control, stacked/collapsible groups, bounded scrolling, full-width search, and non-overflowing nested menus.
- Added regression checks for named `action` controls, mixed Store catalog shapes, Builder asset base paths/WYSIWYG initialization contract, and responsive Administration navigation markup.

# DivisionDesk Core 4.2.4

## AJAX endpoint regression hotfix
- Fixed a shared fetch-layer DOM collision where forms containing an input named `action` shadowed the native `HTMLFormElement.action` property. This produced requests to `/public/[object HTMLInputElement]` and HTTP 403 responses.
- The shared Core AJAX layer now resolves the endpoint from the literal `action` attribute with `getAttribute('action')`, so named form controls cannot alter the request URL.
- Applied the same safe endpoint resolution to the browser installer and direct Legal Policies/Search form JavaScript paths.

## Store catalog completeness
- Store catalog extraction now merges flat `packages` arrays with grouped Modules, Themes, Widgets, Site Templates/Complete Sites, and Page Layout buckets from the same Server response.
- Mixed catalog response shapes are de-duplicated by canonical package type + slug instead of returning early after the flat modules list and silently dropping other families.

## Regression coverage
- Added an explicit `[object HTMLInputElement]` endpoint regression check.
- Added a mixed flat+grouped five-family catalog regression test.

# DivisionDesk Core 4.2.3

## Store stabilization
- Store mutations no longer self-post to `/public/store.php`; the Store page is GET-only and all install/update/download/apply actions target the dedicated JSON `/store-action.php` endpoint.
- Modern Server catalog responses are normalized from flat `packages` arrays or grouped package-family buckets. Modules, Themes, Widgets, Site Templates, and Page Layouts all share one canonical client contract.
- Package type aliases/fields such as `package_type`, `widget-pack`, `site_template`, `complete-site`, and `page_layout` are normalized before Store categorization.
- A successful modern catalog remains authoritative even when optional legacy repository sources fail, including legacy DD-PKG-012 failures.
- Server-advertised Store catalog endpoints remain preferred; `/api/store-catalog.php` is the canonical compatibility default and `/api/store.php` remains legacy fallback only.

## Security / request integrity
- Added explicit CSRF enforcement to authenticated Core mutation paths that were still relying only on login/session state: Media, Media Edit, Navigation, Page metadata, Page Builder JSON saves/template/reusable actions, Site Profile, Template export, Platform sync, revision restore, administrator account changes, administrator login, member login, and member verification.
- Page Builder custom JSON POSTs now send `X-CSRF-Token` and return HTTP 419 JSON on invalid tokens.
- Existing fetch/AJAX interception remains in place; action-specific busy labels/spinners and duplicate-submit prevention continue to apply.

## Regression tests
- Added Store regression coverage for grouped five-family catalogs, Server Official trust preservation, legacy DD-PKG-012 isolation, no Store self-posting forms, and dedicated Store action endpoint contracts.
- Fresh SQLite schema execution and Events Registration 2.0 check-in schema verification remain clean.

# DivisionDesk Core 4.2.2

## Store catalog endpoint/failover hotfix
- Core Store now prefers the Server-advertised Store catalog endpoint and recognizes `/api/store-catalog.php` as the current canonical endpoint, with `/api/store.php` retained only for compatibility.
- A successful modern catalog response is authoritative even when `packages` is empty; failure of an optional legacy repository endpoint no longer blanks the Store.
- Last-known-good catalog responses are cached for temporary Server outages.
- Heartbeat can advertise future endpoint changes through `endpoints.store_catalog` / `store_catalog_endpoint`, eliminating hard-coded endpoint coupling.
- Store errors identify the failing Server catalog source rather than implying that local Core scanned the remote Server file.

# DivisionDesk Core 4.2.1

## 4.2.1 SQLite upgrade hotfix
- Fixed the 4.1.x -> 4.2.x SQLite migration failure `no such column: checkin_token_hash`.
- SQLite schema application is now two-pass and idempotent: compatible CREATE statements run first, missing Events Registration 2.0 columns are added, then the full schema/index set is re-applied strictly.
- Migration errors in the Registration 2.0 column-add phase are no longer silently swallowed.
- Added an explicit regression test for an existing `event_registrations` table that predates `checkin_token_hash`.


## Added
- Core-owned Events and Registration 2.0: configurable attendee types, capacity/waitlists, flexible registration questions/options, per-type/option pricing, paid-registration provider handoff, signed QR check-in, printable badges, attendance, cancellation/refund workflows, CSV/reporting, confirmations and scheduled reminders.
- Core Events administration, registration setup, public registration/confirmation, badge, export and check-in endpoints.
- Events permissions and Administration navigation.

## Changed
- Existing legacy Events add-on installations are enhanced non-destructively: Core reuses the existing Events/registration tables and adds missing Registration 2.0 fields while leaving the mature legacy provider enabled so recurrence, categories, ICS/API, import/export and Builder widgets are not lost during upgrade.
- Server/Store trust metadata now normalizes current and legacy authority fields before restricted package validation.
- Server responses containing HTML instead of JSON now identify that condition explicitly and include a bounded diagnostic excerpt.

## Fixed
- Fixed Core Store catalog regression where first-party packages could be misclassified as Community when Server used legacy Official metadata, causing false DD-PKG-012 security errors against Official code.
- Fixed native Events QR generation mask/format encoding discovered by decoder QA.
- Fixed dollar-to-cent conversion for integer-looking UI prices such as `25`, which must mean $25.00 rather than 25 cents.

## Security
- Third-party validator rules remain unchanged in strength. Official bypass is granted only from remote Server/Store trust authority; package-local `official`/`trusted` flags do not elevate trust.

# DivisionDesk Core Changelog

## 4.1.0 — 2026-08-18

### Shared Client/Server module architecture
- Added the formal package runtime contract: `client`, `server`, or `both`. Legacy packages remain `client` for backward compatibility.
- Core now rejects Server-only packages during dependency planning, quarantine validation, installation, module boot, lifecycle execution, and package Help discovery.
- Package-local metadata cannot widen the runtimes authorized by DivisionDesk Server.
- Added `Integration::runtime()` and `PackageContext::runtime()` so portable `both` packages can adapt through the SDK without relying on host internals.
- Recorded package runtime in Core-generated `.security.json` metadata and local package inventory.

### Publishing/distribution integration
- Formalized the existing destination registry as `DistributionRegistry`, with package ownership, package-qualified IDs, optional capability enforcement, duplicate protection, and delivery lifecycle events.
- `Registry::destination()`, `Integration::destinations()`, and `Integration::distribute()` allow future Publishing to discover Website, email, Social Media, and other installed delivery providers without hard-coded module dependencies.
- Destination delivery emits `distribution.before`, `distribution.after`, and `distribution.failed`.

### Page Builder charts
- Added a native Chart block to the drag/drop Page Builder.
- Supports bar, line, and donut visualizations from editable label/value data.
- Charts are rendered by Core without a third-party JavaScript dependency and include an accessible data table.
- Chart configuration is preserved in normal Page Builder layouts, Page Layouts, reusable sections, and Site Templates.

### Release rules
- Existing fetch/AJAX busy-state rules remain mandatory. No new state-changing browser endpoint was introduced in this revision.
- PHP/JavaScript syntax, runtime-target failure paths, destination registration/delivery, chart rendering, Help documentation, Core integrity, and ZIP integrity are release gates.

## 4.0.0 — 2026-08-18

### Platform services
- Formalized the once-per-minute Core scheduler/background-job dispatcher, package Smart Action scheduling, job locking/retry diagnostics, and corrected Administration/Help cron guidance to `* * * * *`.
- Added provider-based public Site Search with Core page/layout indexing, snippets, JSON results, AJAX results with a visible Searching spinner, and package search-provider registration.
- Added first-party Newsletter Signup, Site Search, and Organization Profile Page Builder widgets. Newsletter Signup delegates to a registered Communications Smart Action rather than duplicating mailing-list logic in Core.
- Added organization context/catalog/provisioning services so DivisionDesk Server can supply organization types plus required/recommended/optional package guidance and Core can install required dependencies.
- Added module-owned page/navigation registration and capability-provider registration to the Integration SDK.

### Page Builder, templates, and site composition
- Preserved drag/drop + WYSIWYG authoring, Page Layouts, reusable sections, complete Site Templates, theme switching, and 25-revision behavior while adding organization/capability conditional content.
- Added server-side rich-text sanitization before rendered WYSIWYG content reaches the public page; unsafe script/event/javascript URL content is removed even if saved content was modified outside the editor.
- Added organization-aware Core widgets and template condition evaluation without coupling templates to a particular membership or organization module.
- Existing Site Template application continues to create a backup before merge/replace and Page Layouts continue to receive fresh builder IDs on application.

### Store, dependencies, and package trust
- Expanded dependency planning for required/optional/conflicting packages, Core/PHP compatibility, capability dependencies, version constraints, cycles, and uninstall dependent checks.
- Added local Package Security controls for disabling packages, reducing Server trust, and denying optional capabilities. Local policy cannot elevate trust.
- A locally downgraded Official package is revalidated under its reduced trust rules before execution; packages that cannot satisfy the restricted model are blocked with an administrator notice.
- Added cryptographic SHA-256/RSA package-signature verification support for Store packages and Core release packages when DivisionDesk Server supplies signing metadata. Modified signed artifacts fail verification.
- Hardened restricted-package analysis against PHP global state, ambient session/environment/cookie access, direct Core/database access, process execution, direct stream/filesystem/network primitives, shell backticks, dynamic includes, undeclared networking/capabilities, unsafe JavaScript globals, malformed manifests, duplicate IDs, and archive traversal/symlinks.
- Added package-qualified identity enforcement and local package security inventory/diagnostics.

### Mediated package capabilities
- Expanded PackageContext/WidgetContext with least-privilege organization, viewer, storage, scheduler, and HTTP capabilities.
- Package storage is isolated in Core-managed settings storage with a bounded JSON payload.
- Mediated HTTP enforces HTTPS, authorized hosts, DNS resolution, private/reserved-network SSRF blocking, no URL credentials, redirect suppression, bounded timeout/response size, and audit logging.

### Legal & Policies Wizard
- Added Website → Legal & Policies Wizard for Privacy Policy, Terms of Use, Cookie Policy, Accessibility Statement, Website Disclaimer, Copyright/Intellectual Property Notice, and capability-relevant refund/payment/account policies.
- Wizard supports Preview before publishing, effective-date/jurisdiction/contact/site-practice inputs, normal editable Page Builder output, policy-profile metadata, and version history through Page Builder revisions.
- Added `Registry::legalPolicy()` so modules can contribute capability-aware policy/disclosure content while Core retains applicability, sanitization, preview, publishing, and revision control.
- Generated content is explicitly presented as an editable starting template/workflow aid rather than individualized legal advice.

### Unified UI and accessibility
- Added reusable Core UI helpers and Developer → UI Showcase for notices, empty states, badges, spinners, progressive disclosure, validation, and fetch/AJAX conventions.
- Added the public icon-only Accessibility control on the left side with text-size and contrast preferences; public footer injections remain excluded from Administration/API responses.
- Preserved the Core-wide fetch-first POST layer. New/custom asynchronous actions use action-specific busy labels/spinners, `aria-busy`, duplicate-action prevention, and explicit success/error feedback.
- Added explicit CSRF protection to Store state-changing actions and Automatic Updates controls; corrected legacy Theme activation to a protected POST action.

### Help, roles, diagnostics, and acceptance testing
- Added automatic package-provided Help ingestion for modules, themes, widgets, Site Templates, and Page Layouts using safe package-relative Help files or inline topics.
- Retained granular role/permission administration and capability-driven Administration visibility as the authorization foundation for the new services.
- Expanded System Health into a simple attention summary backed by database, permissions, Server heartbeat, scheduler, queue, ZIP, update-writability, and acceptance-target checks.
- Added protected Reference Host Acceptance Tests for explicitly authorized demo/test/development clients. The suite exercises real database rollback, Core integrity, Page Builder save/revision cleanup, scheduler/queue contracts, search/widgets, multiple widget instances, sanitization, conditional content, trust policy, cryptographic sign/tamper verification, ZIP quarantine validation, organization/legal generation, and authenticated/CSRF endpoint contracts; results can be reported to a Server-provided acceptance endpoint.

### Update/install reliability
- Preserved update preflight writability checks, maintenance lock, transaction backup, database migration hook, post-copy version verification, automatic rollback, and user rollback backups.
- Core update ZIPs now use the same hardened archive path/symlink validator as Store packages and can be cryptographically signature-verified before extraction.
- Browser/CLI installer and updater continue to create sane writable paths and fail before mutation when PHP cannot safely write the incoming tree.

### Release rules
- Fetch/AJAX with visible busy feedback, syntax checking, error-path testing, endpoint testing, input preservation on recoverable errors, Help updates, and explicit reporting of environment-limited tests remain mandatory release gates.

## 3.9.0 — 2026-08-18

### Integration SDK
- Expanded the existing Core event bus into a package-aware, priority-ordered integration contract while preserving existing `Registry::eventListener()` compatibility. Listener failures are isolated, logged, and do not stop unrelated listeners.
- Added capability-protected, package-qualified Smart Actions through `Registry::smartAction()` / `SmartActionRegistry`. Smart Actions can be discovered without hard-coding another module and emit before/after/failed lifecycle events.
- Added authenticated `/integration-actions.php` JSON discovery/invocation endpoint with server-side capability enforcement, CSRF protection, input validation, and explicit JSON failures.
- Added `Registry::dashboard()` / `DashboardRegistry` so modules can contribute capability-protected dashboard cards without modifying Core dashboard source. Failed dashboard contributions are logged and isolated.
- Added Integration SDK visibility to Developer & Advanced for registered Smart Actions, event listeners, ownership, priority, capabilities, and dashboard contributions.

### Fetch/AJAX interaction standard
- Added reusable `DivisionDeskFetch.request()` and `DivisionDeskFetch.busy()` APIs for custom asynchronous interfaces.
- Core fetch-first POST forms now replace the initiating control with an action-specific spinner/status such as Loading, Saving, Publishing, Installing, Sending, Uploading, Updating, Removing, Applying, or Preparing while awaiting the response.
- Busy controls use `aria-busy`, prevent duplicate submission, restore their prior label afterward, and respect reduced-motion preferences.
- Updated Page Builder custom fetch operations to use the shared busy-state helper for Save, reusable-section Save, and template Apply operations.

### Developer and Help documentation
- Added `docs/INTEGRATION-SDK.md`, expanded the Module SDK, and added a searchable Help Center topic covering events, Smart Actions, dashboard hooks, loose coupling, capabilities, and the asynchronous busy-state standard.
- Existing package security/trust requirements remain authoritative and apply to integrations; events and Smart Actions do not bypass package capability boundaries.

### Release requirements
- PHP and JavaScript syntax checks, integration/error-path unit tests, endpoint contract checks, fetch busy-state checks, Core integrity verification, and ZIP integrity are release gates. Live database-backed endpoint execution remains a target-host acceptance test when the build environment lacks PDO drivers.

## 3.8.1 — 2026-08-17

### Package security and trust
- Added a quarantine-first package security validator to the Store installation path. Restricted package code is validated before it can replace an installed module, theme, or widget.
- Added externally assigned `official`, `trusted`, and `community` trust handling. Package-local author/developer/official claims never grant trust.
- Added stable `DD-*` security errors for prohibited global state, loose helper symbols, direct session/database/Core-service access, shell/process execution, filesystem mutation, direct network primitives, remote-code loading, malformed permissions, and JavaScript global leakage.
- Added package-qualified widget machine IDs (`package-id:widget-id`) with duplicate protection and backward lookup for pre-3.8.1 standalone `widget.slug` builder references.
- Added read-only `PackageContext` / `WidgetContext` runtime objects for standalone widgets.
- Added mediated HTTPS `PackageHttpClient` with authorized-host enforcement, HTTPS-only policy, private/reserved-network SSRF prevention, bounded timeout/response size, and no automatic redirects.
- Added Core-generated `.security.json` package records containing trust and granted permissions. Runtime permissions are read from that record rather than directly from manifest requests.
- Added package trust/security visibility to Developer & Advanced.
- Added Help Center and SDK/package-security documentation for the hard extension rules.

### Deferred hardening
- Local trust downgrade/capability denial UI, cryptographic package signing, deeper AST analysis, and additional mediated privileged capabilities remain explicit backlog items and are not presented as completed in this release.

## 3.8.0 — 2026-08-17

### Added
- WYSIWYG rich-text editing inside drag-and-drop Page Builder text blocks, including paragraph/headings, bold, italic, underline, lists, links, and an HTML source toggle.
- Organization-level metadata for standalone and module widgets, with Page Builder compatibility guidance.
- DivisionDesk Server announcement ingestion through the existing platform heartbeat so Server notices can appear in the administrator notification center.
- Server-provided admin push enrollment configuration can now participate in the Core push prompt alongside module push providers.

### Changed
- Page Builder continues to support installed Page Layouts, reusable sections, Site Templates, module components, standalone widgets, and module widgets while adding richer visual authoring.
- Browser notification Help now explains that Core/Server announcements as well as module alerts can use the administrator notification channel.

### Release requirements
- Changed browser actions remain fetch/AJAX based. PHP and JavaScript syntax, error paths, changed endpoints, and Help documentation are release-gate requirements.

## 3.7.0 — 2026-08-15
### Database portability
- Added Configuration → Database with a guided SQLite ↔ MySQL / MariaDB migration workflow.
- Destination connection and emptiness are checked before copying begins.
- Public write actions are briefly paused during the copy so the source cannot change halfway through verification.
- DivisionDesk creates rollback protection and leaves the source database untouched.
- Core and installed-module tables are discovered dynamically rather than relying on a Core-only table list.
- Data is copied in small fetch-driven batches with visible progress.
- Indexes, composite keys, and foreign-key relationships are recreated.
- Every table is verified by row count and a deterministic content checksum before activation.
- DivisionDesk switches config only after all tables pass verification; failed activation restores the prior configuration.
- Cancelling a failed/incomplete move cleans up the temporary destination copy.
- A stale migration lock expires automatically so an abandoned browser session cannot permanently block public submissions.

### Administration notifications
- Added a reusable Administration toolbar notification center for Core and installed modules.
- The notification bell is hidden when there are no unread alerts.
- Clicking the bell opens a compact flyout of unread alerts; each alert can link directly to the screen or record that needs attention.
- Added module registration APIs for administration alert providers and browser-push enrollment providers.
- Core Admin Notices also participate in the notification center.

### Browser notifications
- Administration can show a simple Enable Browser Notifications banner when an installed module supplies a compatible push provider and the current browser/device is not subscribed.
- The banner explains what notifications do and keeps advanced implementation details out of the normal workflow.
- Enrollment happens without leaving or refreshing the Administration page.

### Fetch-first forms
- Added a Core-wide POST form submission layer using fetch.
- Normal POST forms no longer perform browser POST navigations, eliminating Confirm Form Resubmission prompts.
- Existing page-specific fetch handlers continue to take precedence.
- File uploads are supported through FormData; download responses are handled as downloads.
- Redirecting POST actions are followed with fetch and the resulting Administration content is updated in place.
- The browser installer uses the same fetch-first behavior.
- The Core audit found no browser POST form outside the fetch-first coverage path.

## 3.6.5 — 2026-08-15
### Administration usability
- Admin navigation items may expose a live unread badge.
- Badge counts refresh with lightweight fetch polling every 20 seconds without a page reload.
- Badge polling is opt-in per registered admin item and leaves navigation usable if an optional module endpoint is unavailable.

## 3.6.4 — 2026-08-15
### Added
- PublicFooterRegistry and `Registry::publicFooter()` for module-owned site-wide public UI.
- Public footer injections are excluded from Administration/API responses.

## 3.6.3 — 2026-08-14
### Fixed
- Restored bounded HTTPS redirect following in the cURL Platform transport. Core 3.6.2 could treat a normal canonical redirect as a non-JSON API response.
- DivisionDesk Store no longer silently swallows every Store/Repository endpoint failure and renders an apparently blank catalog.
- If all catalog endpoints fail, Store now displays the actual upstream transport/API errors while leaving the Administration page usable.
- Store API and legacy repository requests use an 8-second bounded timeout.

### QA
- Full PHP syntax pass, JSON parsing and JavaScript syntax checks performed across the current Core, Server and Communications packages.
- Core verification manifest regenerated after the final 3.6.3 contents were frozen.

## 3.6.2 — 2026-08-14
### Fixed
- DivisionDesk Server API errors are no longer collapsed into the generic `Could not contact DivisionDesk Server`.
- Platform HTTP transport prefers cURL when available and preserves HTTP status plus JSON error bodies.
- Stream fallback retains HTTP error bodies where supported and reports underlying transport errors.
- Server responses with `{ok:false,error:"..."}` are surfaced directly to modules.
- Invalid/non-JSON Server responses include a short safe response excerpt for diagnostics.

## 3.6.1 — 2026-08-14

### Fixed
- Module database migrations now execute before `Install.php` or `Update.php`.
- Fresh module installs no longer run both the install hook and the update hook.
- Module updates receive both `from_version` and target `version` lifecycle context.
- Store-time Addon registration now uses the same scoped Registry context as normal module boot.
- Fixes installation of modules that seed tables created by migrations, including Communications.

## 3.6.0 — 2026-08-14

### Added
- Renamed the SSH bootstrap installer to **`DivisionDesk-install`**.
- Added single-file **`divisiondesk-install.php`** browser installer for installations without SSH.
- Browser installer uses local filesystem installation first, with FTP, FTPS, SFTP and manual ZIP fallbacks.
- FTP/FTPS/SFTP credentials are request-only and are never persisted.
- CLI and browser installers consume the same formal DivisionDesk Core release-manifest contract.
- Installer bootstrap self-cleanup/self-disable integration with successful Website Setup.
- Core installer/verification service plus `bin/core-verify.php` groundwork for future guided repair of missing/changed Core files.
- Formal release manifest installer metadata: current version, package URL, SHA-256, exact package size, minimum PHP and installer API compatibility.
- Persistent background Job Queue with priorities, delayed execution, retry/backoff, failed jobs, idempotency keys, worker heartbeat and retention cleanup.
- Job-handler registry so modules can submit background work without implementing their own cron system.
- Encrypted Secret Vault using AES-256-GCM with a site-local key stored outside the public web root.
- Shared transport interface/registry for Email, SMS, Push and future communication providers.
- Shared authenticated-webhook/HMAC helper and webhook activity log.
- Core Event Bus for module-to-module notification triggers.
- Administration Job Queue diagnostics, manual worker execution and failed-job retry.

### Changed
- Installation documentation now uses `DivisionDesk-install`; legacy `scv-install` naming is no longer presented to users.
- Core updater accepts the formal `package_url` / `sha256` / `package_size` release manifest while retaining compatibility aliases.
- Scheduler now processes the shared Job Queue and cleans old completed jobs.
- Administration flyout sizing/spacing refined to reduce oversized module menus.

### Security
- Provider credentials can now be stored encrypted rather than in ordinary site settings.

## 3.5.4 — 2026-08-14

### Added
- Persistent **Remember Me** authentication for administrators using revocable, hashed device tokens.
- Automatic restoration of remembered administrator and member sessions on all DivisionDesk web requests.
- Administration **Email Delivery** settings with SMTP, PHP `mail()`, and Development/Log transports.
- SMTP test-mail tool and mail-attempt log.
- Administration navigation subgroups/flyouts so module tools can be grouped under their parent module.
- Module registration context so installed modules automatically receive a navigation subgroup when they register Organization tools.
- Changelog page in Administration.
- Formal `CHANGELOG.md` package convention in the Module SDK.

### Changed
- DivisionDesk production platform/server default is now `https://divisiondesk.com/`.
- Public `Member Login` navigation changes to **Logout** while a member or administrator is authenticated.
- Administration navigation shows the current administrator account and Logout links.
- Page Builder widget blocks now display the actual widget name, selected layout, and key configuration settings.
- Widget inspector now uses registered widget metadata to generate layout and setting controls.
- `Powered by DivisionDesk` now links to `https://divisiondesk.com/`.
- Email delivery status distinguishes SMTP acceptance, PHP-mail queue acceptance, development logging, and failures.

### Fixed
- Page Builder now preserves the widget identifier when a widget is dragged into a page. Previously a newly inserted widget could be saved without its widget key and later render as `Widget unavailable:`.
- Core package/server URL fallbacks no longer reference temporary project domains.

## 3.5.3 — 2026-08-14

### Fixed
- Administration registry Core items no longer disappear when an installed module registers its Administration destinations before Core boot.
- Help Center Core topics no longer disappear when module help topics register first.

## 3.5.2 — 2026-08-14

### Fixed
- Hardened Administration registry handling of short/malformed navigation definitions that could cause `Undefined array key` errors.

## 3.5.0–3.5.1 — 2026-08-14

### Added
- Capability-driven Administration.
- Grouped Administration navigation.
- Help Center and Administration search.
- Automatic update scheduler/background-job foundation.
- Module lifecycle and migration framework.
- Audit log, notices, system health, and developer tools.
- Standardized DivisionDesk footer.

## 3.4.0 — 2026-08-14

### Added
- Universal Variable Registry and Site Profile.
- Role/data resolver architecture.
- Standalone and module Widget registries.
- Site Template 2.0 support.
- Page Layout and Site Template export foundations.
Site Template

Georgia Division SCV Signature Site 3.4.0

development · published · 2026-09-14T20:30:49+00:00

3.4.0 fixes Events widget keys, adds an accessible low-overhead hero carousel, ancestor-search placement, updated homepage news/events composition, heading-order accessibility and performance-oriented local asset references. Use the included slug-aware live updater for an existing Georgia installation; do not use Core Replace.

Theme

Georgia Division Signature 3.4.0

development · published · 2026-09-14T20:30:46+00:00

Performance-focused 3.4.0 removes embedded base64 images from CSS, packages local assets, fixes Events widget namespacing, tightens Storefront, refines Publishing/Camps, preserves registry-owned member navigation and adds accessible responsive hero presentation.

Site Template

Georgia Division SCV — Signature Site 3.3.0

development · published · 2026-09-14T09:48:11+00:00

Theme

Georgia Division Signature 3.3.0

development · published · 2026-09-14T09:48:08+00:00

Site Template

Georgia Division SCV — Signature Site 3.2.0

development · published · 2026-09-14T09:23:54+00:00

Theme

Georgia Division Signature 3.2.0

development · published · 2026-09-14T09:23:51+00:00

Module

Membership Manager 1.3.21

development · published · 2026-09-14T09:08:59+00:00

Public endpoint self-repair: Membership Manager now ensures missing admin/API endpoint shims during addon registration, matching the proven DivisionDesk module pattern. Existing endpoint files are left untouched so normal requests and scheduler runs do not rewrite them every minute. Preserves all v1.3.18 MySQL compatibility fixes and v1.3.19 endpoint validation.

Full package changelog
# Changelog

## 1.3.21 - suEXEC-Safe Public Endpoint Permissions

- Changes generated public PHP endpoint permissions from `0664` to `0644` so Apache suEXEC does not reject them as writable by others.
- Changes the generated Rosters API directory mode from `0775` to `0755` for the same shared-hosting compatibility reason.
- Keeps the 1.3.20 create-if-missing behavior so normal bootstrap/heartbeat requests do not rewrite existing Membership Manager endpoint shims.

## 1.3.20 - Public Endpoint Self-Repair
- Ensures Membership Manager public endpoint shims during `Addon::register()` so missing `membership-*.php` files are recreated on a normal module bootstrap.
- Existing endpoint files are no longer rewritten merely because the addon is registered or the scheduler runs.
- Keeps explicit write verification/errors when a missing endpoint actually needs to be created.
- Root `.htaccess` is only rewritten when the Rosters API block is genuinely absent.
- Preserves the v1.3.18 MySQL reserved-word compatibility fixes and the v1.3.19 endpoint repair migration.

## 1.3.19 - QA
- Ensures Membership Manager public endpoint shims are generated from migration 008, covering install/reinstall paths that run migrations but skip the optional module lifecycle hook.
- Makes critical PublicEndpoints writes fail explicitly with the exact path instead of silently suppressing filesystem errors.
- Verifies all required membership endpoint shims exist after generation.
- Retains the v1.3.18 MySQL reserved-word compatibility fixes.

# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Membership Manager 1.3.20

development · published · 2026-09-14T08:50:57+00:00

Public endpoint self-repair: Membership Manager now ensures missing admin/API endpoint shims during addon registration, matching the proven DivisionDesk module pattern. Existing endpoint files are left untouched so normal requests and scheduler runs do not rewrite them every minute. Preserves all v1.3.18 MySQL compatibility fixes and v1.3.19 endpoint validation.

Full package changelog
# Changelog

## 1.3.20 - Public Endpoint Self-Repair
- Ensures Membership Manager public endpoint shims during `Addon::register()` so missing `membership-*.php` files are recreated on a normal module bootstrap.
- Existing endpoint files are no longer rewritten merely because the addon is registered or the scheduler runs.
- Keeps explicit write verification/errors when a missing endpoint actually needs to be created.
- Root `.htaccess` is only rewritten when the Rosters API block is genuinely absent.
- Preserves the v1.3.18 MySQL reserved-word compatibility fixes and the v1.3.19 endpoint repair migration.

## 1.3.19 - QA
- Ensures Membership Manager public endpoint shims are generated from migration 008, covering install/reinstall paths that run migrations but skip the optional module lifecycle hook.
- Makes critical PublicEndpoints writes fail explicitly with the exact path instead of silently suppressing filesystem errors.
- Verifies all required membership endpoint shims exist after generation.
- Retains the v1.3.18 MySQL reserved-word compatibility fixes.

# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Membership Manager 1.3.19

development · published · 2026-09-14T08:34:51+00:00

Installer endpoint repair: preserves the v1.3.18 MySQL reserved-word compatibility fixes and moves Membership Manager public endpoint generation onto the guaranteed migration path. Required endpoint writes are now verified and fail with an explicit error instead of being silently suppressed.

Full package changelog
# Changelog

## 1.3.19 - QA
- Ensures Membership Manager public endpoint shims are generated from migration 008, covering install/reinstall paths that run migrations but skip the optional module lifecycle hook.
- Makes critical PublicEndpoints writes fail explicitly with the exact path instead of silently suppressing filesystem errors.
- Verifies all required membership endpoint shims exist after generation.
- Retains the v1.3.18 MySQL reserved-word compatibility fixes.

# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Membership Manager 1.3.18

development · published · 2026-09-14T08:27:51+00:00

MySQL compatibility repair: quotes reserved/keyword-sensitive identifiers used by Rosters schema and DML, including `rank`, `required`, and `sensitive`, so fresh installs and reinstalls complete on modern MySQL. This allows the normal install lifecycle to reach PublicEndpoints::ensure() and recreate the Membership Manager endpoint shims.

Full package changelog
# Membership Manager Changelog

## 1.3.18 QA
- Fixed a second modern-MySQL install failure caused by the SQL keyword `sensitive` in `roster_custom_fields`.
- Quoted `required` and `sensitive` consistently in custom-field schema creation and INSERT/UPDATE SQL to prevent further reserved-word parser failures.
- Retains the v1.3.17 `rank` compatibility fix for ancestor schema and writes.
- No roster data is purged or reset by this repair.

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Module

Membership Manager 1.3.17

development · published · 2026-09-14T08:24:27+00:00

MySQL compatibility repair: quotes the reserved ancestor column `rank` in schema creation and ancestor INSERT/UPDATE SQL so fresh installs and reinstalls complete on modern MySQL. This also allows the normal Rosters install lifecycle to reach PublicEndpoints::ensure() and recreate the Membership Manager public endpoint shims.

Full package changelog
## 1.3.17 QA
# Membership Manager Changelog

## 1.3.17 QA
- Fixed modern MySQL installation failure caused by the reserved SQL keyword `rank` in `roster_ancestors`.
- Quoted ancestor column identifiers in both schema DDL and ancestor INSERT/UPDATE statements so ancestor writes remain compatible after install.
- Restores the normal installation/update path so `PublicEndpoints::ensure()` can create the Membership Manager endpoint shims after migrations complete.
- No roster data is purged or reset by this repair.

## 1.3.16 — 2026-09-13
- Normalize Core `level_1`..`level_4` organization levels through `Terminology::legacyKey()` before applying SCV National/Division/Camp DNR access rules.
- Preserve existing Membership Manager membership levels, role keys, stored scope types, APIs, dues behavior, and database schema.
- Minimum Core is now 4.6.39, the neutral hierarchy compatibility baseline.

## 1.3.15 — 2026-09-06
- Requires Core 4.6.21 security-schema repair.
- Role/permission readers use DISTINCT/grouped database queries so damaged legacy security tables cannot exhaust PHP memory.

## 1.3.14

- Fixes Roles & Offices modal submission so disabling the button no longer disables/omits all POST fields, including the CSRF token.
- Fresh-CSRF retry now updates the actual FormData payload before retrying.
- Refreshes the current effective session after any role assignment/end so an Administrator assignment to the uniquely linked current member takes effect immediately.

## 1.3.13
- Adds exact, unambiguous administrator-email-to-member identity resolution for Core's unified effective-role refresh.
- Ensures an organizational Administrator role grants full roster scope even if a browser session was stale, while refusing ambiguous duplicate-email auto-linking.
- Keeps Membership Manager as the authoritative member-role assignment store; no dues, status, import, portal, or payment behavior is changed.

## 1.3.12
- Makes Membership Manager `Roles & Offices` the single authoritative member-role assignment store when paired with Core 4.6.17+.
- Migrates successfully mappable legacy Core `member_role_assignments` into roster role assignments during install/update, deleting only rows that were successfully migrated.
- Preserves unknown/unmappable legacy rows rather than deleting data; standard DivisionDesk presets and custom access roles are mapped conservatively.
- Stops the roster role provider from re-merging the legacy Core assignment store after migration.
- Automatically retries a member-modal role assignment once with a freshly rendered CSRF token after a 419/stale-session response; a failed CSRF check still performs no write.
- Refreshes the current member session immediately when that member's role is assigned/ended.
- Does not change dues, member status, search, import/export, Finance, or member-portal behavior.

## 1.3.11
- Repairs Membership Manager Settings role/permission administration without changing dues, status, import, search or member portal behavior.
- Adds preset `Administrator` organizational role mapped to Core `organization_administrator` full control.
- Role definition list is defensively de-duplicated by role key.
- Permission editing now opens one office at a time instead of rendering every role × permission combination on a single page.
- Requires Core 4.6.16 for the full-control Administrator access role and repaired Access pages.

## 1.3.9
- Adds `RoleProvider::memberByScvId()` for authorized runtime integrations such as Events registration auto-fill.
- Returns current member identity, address/contact and camp number directly from the authoritative roster.
- Retains all 1.3.8 late-fee and DNR/status behavior.

## 1.3.8
- Late-fee eligibility derives from the member's actual paid-through date.
- Paid through 2026-07-31 + late after 08-31 correctly applies the configured fee after 2026-08-31.
- Handles year-crossing late-fee schedules.
- Retains 1.3.7 DNR/status and donation-fund work.

## 1.3.7
- Yearly / life / DNR controls are now editable directly from the common member-detail Membership tab for authorized users.
- Active/Inactive is derived from deceased status, any DNR status, or National yearly dues being more than the configured number of months overdue.
- Adds a configurable overdue threshold (default 12 months), daily reconciliation, and update-time cleanup of inconsistent seeded/manual Active flags.
- Donation options are now mapped to active Finance funds and carry that fund through checkout/accounting.
- Retains the 1.3.6 late-fee cycle-date correction and itemization.

## 1.3.6
- Fixes renewal-cycle late-fee dates. A 2027 renewal with a 07-31 expiration and an 08-31 late-fee cutoff now becomes late after 2026-08-31, rather than incorrectly waiting until 2027-08-31.
- Handles year-crossing late-fee schedules correctly (for example, a 12-31 expiration with a 01-31 late-fee cutoff uses 01-31 of the renewal year).
- Makes member-facing late fees explicit in the dashboard coverage card, Payments breakdown, review/checkout, bulk calculated checkout, and receipts.
- Retains independent National / Division / Camp late-fee amounts and dates, DNR hierarchy, life-member rules, donations-while-current behavior, and Finance completion reconciliation.

## 1.3.5
- Adds independent National / Division / Camp status controls for Yearly, NLM/DLM/CLM life membership, and permanent DNR.
- Enforces downward DNR propagation for dues and member login eligibility: National DNR blocks all lower levels; Division DNR blocks Division/Camp; Camp DNR blocks Camp only.
- Life membership is permanent unless changed to DNR and cannot revert to yearly. DNR cannot be reversed through normal editing.
- Stores full paid-through dates using configurable per-level expiration month/day instead of relying on year alone.
- Adds independent National, Division and Camp late-fee dates and amounts, with explicit checkout/receipt itemization.
- Keeps optional donation checkout available even when required dues are fully paid.
- Makes Finance completion acknowledgement explicit so failed cross-module completion can be retried rather than silently requiring the member to visit Payments.
- Extends API/report/import behavior for DNR, life status, full paid-through dates, and effective collectibility.

# 1.3.4.c

- Completes paid Finance transactions back into member dues through the Core Integration SDK, reconciles previously completed Finance payments, adds payment-page return/receipt UX support, clarifies donation configuration, and centers the member-modal close control.

# Membership Manager 1.3.4.b

## 1.3.4.b — Clean member route + exact caret preservation + mockup fidelity

- Fixed the `/my-membership` redirect loop by removing the conflicting physical `my-membership.php` shim; the clean route now renders through Core's module-page router and the photo stream uses a dedicated endpoint.
- Live roster search now preserves the member's latest caret/selection position while typing during an in-flight fetch; it never restores an older cursor position captured at request start.
- Revalidated the approved member-portal mockup as the visual acceptance target for Overview, Profile, Payments, Events, Documents and Directory surfaces.

- Keeps the live roster search field interactive during fetch, aborts stale requests, and preserves focus/caret position.
- Implements the approved member navigation: logged out shows **Login**; logged in shows the member first name and stored photo when available, with Membership Overview, My Profile, Dues & Payments, My Events, Documents & Forms, optional Member Directory, and Logout in one dropdown.
- Removes the redundant top-level Logout link while logged in.
- Brings My Membership dashboard structure to the approved mockup: Member Since, membership-standing card, total due card, payment-coverage visualization, recent payments, and upcoming events.
- Refines Profile & Account into real Profile / Preferences / Account & Security tabs.
- Keeps optional member photos truly optional and uses the stored photo in member navigation only when present.
- Rewords member-facing empty states to avoid implementation/integration jargon.
- Retains the 1.3.3 live filtering, Saved Views repair, Finance configuration gating, API simplification, calculated dues, donation checkout, and member-directory controls.

- Fixed live roster search so an in-flight fetch never disables or blocks the Search field.
- Search now preserves focus and caret position after AJAX result refreshes.
- Older in-flight roster requests continue to be aborted when a newer query/filter request starts.
- Search debounce tuned to 350 ms while remaining fully interactive.


- Streamlined the Members workspace: removed Dues and Paid Through from the filter bar, removed the Filter button, removed duplicate Add Member / Import / Export title actions, and removed Search and API from the left navigation.
- Filters now refresh automatically: debounced text search plus immediate Status, Camp, Role and results-per-page changes. Fetch/AJAX updates do not rewrite the browser URL.
- Fixed Saved Views so they actually restore the saved search/filter/page-size state, remain AJAX-driven, and can be deleted from the Saved Views area.
- Moved API tooling out of the everyday navigation and into Settings → Integrations & Developer Access. Reworked the developer page with plain-language explanations and collapsed advanced sections.
- Online Pay / Pay Selected controls now require DivisionDesk Finance to be both installed and configured with a payment provider. If Finance is installed but not configured, dues remain visible but no working-looking payment action is shown.
- Hardened API payment operations to reject payment creation/completion until Finance is configured.

# Membership Manager 1.3.2

- Completed the member-facing portal inside the active client site header/navigation/footer.
- Added one My Membership public navigation parent with dropdown children for Payments & Receipts, Events, Documents & Forms, Profile & Account, and optional Member Directory.
- Replaced member-selected dues levels with calculated National/Division/Camp obligations and one payable total with explicit included/not-included status.
- Added admin-configured optional donation funds with descriptions, Learn More links, preset/custom amounts, ordering, and all choices unchecked by default.
- Added combined dues + donation checkout/receipt metadata and calculated multi-member officer checkout.
- Added configurable Member Directory visibility (disabled, officers only, all active members), audience, and visible fields.
- Added graceful image MIME validation fallback when PHP Fileinfo is unavailable.
- Reworked member portal pages into dashboard/payments/events/documents/profile/directory views instead of one long form.
- Preserved Finance-aware payment visibility, member self-service security boundaries, Smart Import, APIs, audit, and scoped permissions.

# DivisionDesk Rosters / Membership Manager 1.3.1

- Mockup-conformance UX pass across the Membership Manager admin surface.
- Added a compact module navigation rail while retaining the Core global admin shell.
- Moved results-per-page to the roster footer with 25/50/100/250 choices and a 50 default.
- Added numbered AJAX pagination and preserved user page-size preference.
- Tightened roster density, actions, modal sizing, edit scrolling, card hierarchy and responsive behavior.
- Member photos remain absent unless a real stored photo exists.
- Existing Smart Import, self-service member portal, Finance-aware payment visibility, APIs, permissions, scope enforcement and bulk dues functionality are retained.

# Membership Manager / Rosters Changelog

## 1.3.0 — Completion release

- Added member-facing **My Membership** self-service portal at `/my-membership.php` using the existing Core member-login session when available.
- Members can review National/Division/Camp membership status and DivisionDesk dues transaction history.
- Members can update only permitted self-service fields: preferred name, address, email, phones/SMS, opt-out preferences, optional photo, and member-supplied social links.
- Authoritative SCV ID, camp, membership status, roles, dues state, internal notes, and lifecycle fields remain officer/admin controlled.
- Added self-service photo streaming and profile-save auditing without exposing administrative controls.
- Added self-pay checkout handoff when Finance is installed. Payment buttons remain hidden when Finance is absent.
- Admin **Pay Dues / Pay Selected** controls are hidden when Finance is not installed; **Mark Paid** remains available to authorized officers.
- Payment API creation/completion now also refuses online-payment operations when Finance is absent.
- Checkout now supports either an authorized administrator or the authenticated member who owns a self-service payment request.
- Added a Finance bridge that safely detects Finance/configuration and delegates checkout only through an exposed Finance checkout URL contract; Rosters never handles raw card/bank data.
- Added user-selectable roster page sizes: **25 / 50 / 100 / 250**, default **50**, remembered in the browser.
- Improved primary roster search so multi-word searches are tokenized across name, SCV ID, email, phones and camp (for example `James Adkins`, `Baggett 1864`).
- Retained fetch/AJAX filtering, pagination, loaders, duplicate-click prevention, row-click member workspace, bulk selection, smart import, export, APIs, audit history, roles, ancestors, photos/social links and SQLite performance optimizations.
- Continued use of Core/global admin UI variables for Membership Manager colors and surfaces.
- Raised the release baseline to Core 4.4.1 for the production completion pass.


## 1.2.5 - 2026-08-24

- Production-polished Membership Manager UI aligned with the approved DivisionDesk mockup and global admin styling.
- Canonical AJAX member workspace/modal with in-modal editing.
- Permission-aware checkbox bulk actions for dues workflows.
- `Pay Selected` now enters a review/checkout workflow; when no payment provider is configured, no charge occurs and no member is marked paid.
- `Mark Paid` remains a separate authorized administrative action for payments received elsewhere.
- Hardened permission/scope validation, payment completion validation, and member-edit data integrity.
- Member photo storage is supported but no placeholder image/icon is shown when a photo is absent; social profile links can be stored.
- Production QA and deployment acceptance checklist refreshed.

# Membership Manager Changelog

## 1.2.4
- Polished Membership Manager roster based on the approved DivisionDesk v1.2.4 workflow without copying National's visual design.
- Added checkbox selection for members plus permission-aware bulk dues actions.
- Added **Mark Paid** for National/Division/Camp dues and **Pay Selected** payment-request creation for payment integrations.
- Added `rosters.dues.mark_paid` and `rosters.dues.pay` capabilities; all bulk actions also enforce organizational scope.
- Added optional member-photo storage (JPEG/PNG/WebP, max 5 MB). No photo, icon, or placeholder is displayed unless a photo is actually stored.
- Added member-supplied social-media profile links with platform, handle, and URL fields.
- Added photo/social information to member detail views only when present and authorized.
- Expanded roster search to phone and SMS fields.
- Expanded REST API v1: member create/update, membership summary, social-link read/update, bulk mark-paid, payment-request lookup/completion endpoints.
- API service accounts continue to enforce both capability and organizational scope per action.
- Added `dues.payment.requested` and `dues.payment.completed` integration events and persistent payment-request records. Creating a request never falsely marks a payment complete.

## 1.2.3
- Roster filters and pagination now update with fetch/AJAX instead of full-page reloads.
- Added visible loading overlay/spinner while roster results are loading.
- Entire member rows are clickable and keyboard accessible.
- Redesigned member detail modal with reliable tab labels, compact information cards, status display, responsive layout, and footer actions.


## 1.2.2 — Conservative Email Repair
- Smart Import now treats common placeholders such as `NO EMAIL`, `none`, and `N/A` as an intentionally blank email without warning or row failure.
- Obvious missing-dot mistakes on a conservative list of well-known domains (for example `GMAILCOM` and `HOTMAILCOM`) are repaired automatically and reported as corrections.
- Ambiguous malformed values are never guessed. The member still imports, the email is left blank, and the warning shows the exact original value for administrator cleanup.
- Email quality problems never reject an otherwise valid member row.
- Includes the v1.2.1 SQLite bulk-import, roster-query, AJAX modal, country-default, and warning improvements.

## 1.2.1 — Performance & Import Resilience
- Wrapped Smart Import writes in a single transaction, dramatically reducing SQLite commit overhead.
- Preloaded SCV-ID matches for imports and replaced heavyweight per-row profile loads with lightweight identity lookups.
- Cached audit settings and webhook subscriptions for the request instead of re-querying them on every member change.
- Blank country values now safely default to `USA`, including updates, preventing NOT NULL import failures.
- Invalid email addresses no longer discard otherwise valid member rows; the member imports with a visible warning and blank email.
- Roster list queries now select only visible columns and batch-load role/membership badges for the current page.
- Added SQLite/MySQL indexes for common roster browsing and current-role lookup paths.
- Clicking a member in the roster now opens a lazy-loaded AJAX detail modal; heavy profile data is fetched only when requested.
- Full edit pages remain available from the modal for administrative changes.

## 1.2.0 — Universal File Import
- Added native `.xlsx`, `.xlsm`, `.xltx`, and `.xltm` workbook import using the first worksheet.
- Added native `.ods` OpenDocument spreadsheet import.
- Added Excel 2003 XML / SpreadsheetML and HTML-table spreadsheet import.
- Added automatic detection for comma, tab, semicolon, and pipe-delimited text files, regardless of extension.
- Added UTF-8 BOM and UTF-16 LE/BE text decoding for common Excel exports.
- Added content-based format detection so mislabeled `.xls`/`.csv` exports can still be recognized.
- True legacy binary Excel 97–2003 `.xls` files are supported automatically when PhpSpreadsheet is available; otherwise the importer provides a clear conversion instruction instead of a generic failure.
- XLSX date-formatted cells are converted from Excel serial dates before the existing field normalizers run.
- Smart mapping, learned mappings, custom-field creation, normalization, scope enforcement, and row-level error reporting continue to apply to every supported format.

## 1.1.0 — Smart Import
- Fixed CSV header normalization that could strip uppercase letters before matching.
- Added guided smart column mapping with exact, alias, learned, and high-confidence fuzzy matching.
- Unknown columns now require an administrator choice: map to a standard field, map to an existing custom field, create a custom field, or ignore.
- Confirmed source-header mappings are persisted and reused on later imports.
- Added broader aliases for Salesforce-style and common membership roster headings.
- Added safe import normalization for names, phones, dates, email addresses, state names/abbreviations, ZIP codes, salutations, suffixes, country values, addresses, and booleans.
- Added National membership effective/expiration date import support and equivalent Division/Camp mapping targets.
- Added camp-number inference from values such as `FORT BLAKELEY CAMP 1864` when a dedicated camp-number column is absent.
- Added visible row-level import errors instead of only reporting an error count.
- Preserved SCV ID upsert behavior and scope enforcement.

## 1.0.1
- Security and registry integration revision.

### 1.2.4 production-polish revision — 2026-08-24
- Aligned Membership Manager screens with the approved v1.2.4 mockup while inheriting Core/global admin color variables.
- Retained fetch-based roster filtering/pagination and made loading/busy states consistent.
- Member workspace is the canonical everyday view; editing now opens and saves inside the AJAX modal.
- Member photos remain optional and are rendered only when an actual photo is stored.
- Added member-supplied social link editing/storage to the modal workflow.
- `Pay Selected` now opens a review/checkout page instead of ending at an internal request key.
- Checkout clearly shows selected members, dues level/year, per-member amount and total.
- When no payment provider is configured, checkout explicitly performs no charge and does not mark members paid.
- `Mark Paid` remains a separate permission-checked path for payments completed outside DivisionDesk.
- Added protected `membership-checkout.php` endpoint and retained the pending request object as the integration handoff underneath checkout.
- Display-name rendering now cleans legacy all-uppercase/all-lowercase name parts without rewriting stored source data.

## 1.3.10 — 2026-09-05

### Added
- Exposes Assign Role / Office directly from the member Roles & Offices modal.
- Adds editable Roles & Permissions presets in Membership Manager Settings, backed by existing Core role/capability tables.
- Adds missing standard SCV office definitions/mappings (Camp Webmaster, Lt. Brigade Commander, Division Communications Chairman) without replacing local custom roles.

### Safety
- Preset seeding is additive only. Existing role assignments, custom role definitions and administrator-edited permissions are not removed or reset during update.
- Camp/Brigade/Division scope is derived from the member hierarchy for standard offices and checked against the assigning administrator's existing data scope.
- Dues, status derivation, member import/search, Finance and portal logic are unchanged.
Site Template

Georgia Division SCV — Signature Site 3.1.0

development · published · 2026-09-14T04:29:16+00:00

Theme

Georgia Division Signature 3.1.0

development · published · 2026-09-14T04:29:13+00:00

Site Template

Georgia Division SCV — Signature Site 3.0.1

development · published · 2026-09-14T04:03:02+00:00

3.0.1 pairs with the Home Ownership Repair. The Site Template continues to leave /camps, /news, /events and /shop under their native module ownership.

Theme

Georgia Division Signature 3.0.1

development · published · 2026-09-14T04:02:57+00:00

3.0.1 adds compatibility stylesheet aliases and accompanies the one-time Home page ownership/layout repair for installations where the obsolete georgia-division-site.home module page survived template replacement.

Site Template

Georgia Division SCV — Signature Site 3.0.0

development · published · 2026-09-14T03:49:46+00:00

Theme

Georgia Division Signature 3.0.0

development · published · 2026-09-14T03:49:43+00:00

3.0.0 is a clean visual rebuild; prior generic layouts were not carried forward.

Site Template

Georgia Division SCV — Signature Site 2.1.0

development · published · 2026-09-14T03:37:09+00:00

2.1.0 is the mockup-parity rebuild. It does not create duplicate module-owned /camps, /news, /events or /shop pages.

Theme

Georgia Division Signature 2.1.0

development · published · 2026-09-14T03:37:03+00:00

2.1.0 rebuilds the visual system around the approved Georgia mockups and adds robust styling for native Camps, Publishing, Events and Storefront output.

Module

Georgia Camp Directory 0.1.0

development · published · 2026-09-14T03:31:15+00:00

Full package changelog
# Changelog

## 0.1.0
### Added
- Public Camp Directory module page backed by Core `OrganizationUnitDirectory`.
- Public Camp detail rendering from the authoritative `scv_camps` provider.
- Smart `meeting_time` interpretation for common ordinal-weekday monthly schedules.
- Safe fallback to the original human-readable schedule when recurrence cannot be parsed.
- Next-meeting calculation with month exclusions such as July/December.