Relocate CLAUDE.md from repo root to .mokogitea/ per project convention.
Content updated with focused, repo-specific architecture and rules.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename root source directory from src/ to source/ and update all
references in Makefile, manifest.xml, .gitignore, CI workflows,
and wiki documentation. Internal Joomla namespace paths (src/Extension)
are unchanged as they are plugin-internal structure.
CI workflows updated to check source/ first with src/ fallback for
backward compatibility across repos.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add <licensing> section to manifest.xml with update-server URL
template and dlid flag. Add manifest_licensing.php step to
pre-release workflow to auto-ensure updateservers/dlid tags.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- #96: Move Facebook token from URL query string to Authorization
header in both publish() and validateCredentials()
- #97: Cache Bluesky AT Protocol session tokens in static property
with 90-minute TTL to avoid re-authenticating on every post
- #98: Add auto_send parameter to Mailchimp — calls campaign send
endpoint after creation when enabled (default: off for safety)
- #99: Batch duplicate guard and template loading in
CrossPostDispatcher — reduces N*M queries to 2 bulk queries
- #102: Remove duplicated renderTemplate() from DispatchController,
delegate to CrossPostDispatcher::renderTemplate() (now public)
- #103: Replace deprecated Sidebar API with Joomla 5 toolbar submenu
API, with legacy fallback for Joomla 4 compatibility
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- #92: Replace MySQL-only GET_LOCK with db-agnostic locking — adds
PostgreSQL pg_advisory_lock and timestamp-based fallback
- #94: retryFailed() now includes permanently_failed and cancelled
statuses, not just failed
- #95: Validate scheduled_at datetime via Factory::getDate() in both
PostModel::prepareTable() and PostsController::schedule()
- #100: Add clarifying comment to update SQL for duplicate table def
- #101: Replace fragile LIKE query with JSON_EXTRACT() for evergreen
article detection
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move dlid and blockChildUninstall elements before updateservers and
fix tab indentation to match the 4-space convention used in the rest
of the manifest.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds onAfterRoute hook that checks the update site for a valid
MOKO-XXXX license key and shows a warning message once per session
if missing — directs users to System > Update Sites.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge duplicate ### Added and ### Fixed headings into single sections
and fix version format from 01.00.00 to 01.00.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restores the pre-release workflow without update-stream steps —
updates.xml is now generated dynamically by the license server.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standardize manifest.xml identity block: ensure <name> contains only
the machine identifier (PascalCase) and <display-name> contains the
human-readable label with Joomla extension type prefix. Remove duplicate
<version> tags where present. Update CONTRIBUTING.md from moko-platform
default.
Authored-by: Moko Consulting
C-1: CSRF nonce on OAuth authorize/callback flow
C-2: POST method enforcement on REST dispatch endpoint
C-5: Service credential fields now saved from form to JSON column
(collect cred_* fields, strip prefix, JSON encode on save;
expand back on load for editing)
H-1: Joomla 5 event ArrayAccess pattern for service plugin collection
(reads from Event indices instead of broken by-reference)
H-4: ServiceTable::check() with alias generation, required validation
H-9: WebhookService credential keys match form XML field names,
Bearer/Basic auth headers implemented correctly
M-4: XSS fix — escape $extraClass in ServiceIconHelper::renderIcon()
M-5: Article history HTML injection via setFieldAttribute() instead
of double-escaped XML description attribute
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Category routing rules — new DB table #__mokojoomcross_category_rules
maps Joomla categories to specific services (whitelist). Integrated
into CrossPostDispatcher before per-article filters.
2. Character counter — live JS counter in template editor shows
remaining chars per platform with color coding (green/yellow/red)
3. Service type icons — ServiceIconHelper maps 34 types to Bootstrap
icons, used in services list, posts list, and dashboard
4. Per-service analytics drill-down — ServiceStats view with stats
cards, daily trend chart, recent posts, top articles. Dashboard
service rows are now clickable links.
5. Article editor cross-post history — read-only panel in the
Cross-Posting fieldset showing last 10 post results with status
badges, service names, and timestamps
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add media capability reporting to MokoJoomCrossServiceInterface.
Each plugin now returns its supported media types:
- image, video, gif, document (per platform capability)
- Empty array for text-only services (Nostr, Ntfy, ConvertKit)
Enables the dispatcher to skip media attachments for text-only
services and choose appropriate media types per platform.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>