Files
igny8/igny8-wp-bridge/docs/Plan-based-on-audit.md
2026-01-09 21:53:53 +05:00

25 KiB

Strategic Analysis & Implementation Plan

Current State Assessment

What Works Well

  • Unidirectional flow: IGNY8 → WordPress (correct approach)
  • Comprehensive data mapping: All fields documented
  • Multiple trigger points: Manual + scheduled
  • API authentication: Solid security model
  • Retry mechanism: Celery handles failures

What's Actually Broken/Missing


Critical Gaps (Real Functional Issues)

GAP 1: Incomplete Data Transfer

Problem: The audit shows fields are mapped, but doesn't confirm ALL data actually transfers in one atomic operation.

Current Risk:

  • Featured image might fail → rest of content publishes anyway
  • Gallery images fail → content published without visuals
  • SEO meta fails → content has no SEO optimization
  • Categories fail to create → content published orphaned
  • Sectors/clusters fail → no IGNY8 relationship tracking

What's Missing:

  • Pre-flight validation before starting publish
  • Atomic transaction pattern (all-or-nothing)
  • Dependency chain verification (e.g., author must exist before publishing)
  • Rollback on partial failure

GAP 2: No Publish Count Tracking Back to IGNY8

Problem: You stated requirement #4 isn't implemented anywhere in the audit.

What's Missing:

  • After successful WordPress publish, WordPress must call IGNY8 API to increment:
    • post_publish_count for posts
    • page_publish_count for pages
    • product_publish_count for products
    • taxonomy_sync_count for categories/tags/sectors/clusters

Current State:

  • WordPress reports back assigned_post_id and post_url
  • WordPress does NOT report back publish counts or content type statistics

Impact: IGNY8 dashboard shows incomplete/wrong statistics


GAP 3: Taxonomy Sync Doesn't Track Changes

Problem: You need to track if categories/tags/clusters change in WordPress, but current system doesn't.

Current Flow:

  1. IGNY8 sends: categories: ["SEO", "Marketing"]
  2. WordPress creates/assigns these
  3. If user later adds "Content Strategy" in WordPress → IGNY8 never knows
  4. If user removes "Marketing" → IGNY8 never knows

What's Missing:

  • WordPress hook to detect taxonomy changes on IGNY8-managed posts
  • API call to IGNY8 to update taxonomy associations
  • Endpoint in IGNY8 to receive taxonomy change notifications

GAP 4: Cluster/Sector/Keyword Changes Not Synced

Problem: Similar to taxonomy gap but for IGNY8-specific relationships.

Scenario:

  • Content published with cluster_id: 12
  • User changes in WordPress to cluster_id: 15 via custom field
  • IGNY8 still thinks content belongs to cluster 12
  • Cluster 12 shows wrong content count
  • Cluster 15 missing content in its list

What's Missing:

  • Detection mechanism for meta field changes on _igny8_cluster_id, _igny8_sector_id, _igny8_keyword_ids
  • Sync back to IGNY8 to update relationships
  • IGNY8 API endpoints to handle relationship updates

GAP 5: Manual vs Auto-Publish Flow Not Distinguished

Problem: Both flows use same code path, but they need different handling.

Manual Publish (Button Click):

  • Should publish immediately
  • User expects instant feedback
  • Should override any scheduling
  • Should force re-publish if already published

Auto-Publish/Schedule:

  • Should respect published_at timestamp
  • Should not override manual edits in WordPress
  • Should skip if already published (idempotent)
  • Should handle timezone conversions

What's Missing:

  • publish_mode flag in API payload (manual vs scheduled)
  • Different retry strategies for each mode
  • Different status reporting for each mode
  • Override logic for manual re-publish

GAP 6: No Verification After Publish

Problem: WordPress reports "success" but doesn't verify the content is actually viewable/accessible.

Failure Scenarios Not Caught:

  • Post published but permalink returns 404 (rewrite rules not flushed)
  • Featured image attached but file doesn't exist (upload failed silently)
  • Categories created but not assigned (database transaction partial commit)
  • SEO meta saved but plugin not active (meta stored but not used)

What's Missing:

  • Post-publish verification step
  • Check permalink returns 200
  • Verify featured image URL accessible
  • Verify taxonomies actually assigned (count > 0)
  • Report verification results to IGNY8

GAP 7: Schedule Publishing Timezone Issues

Problem: IGNY8 sends UTC timestamp, WordPress stores in site timezone, confusion inevitable.

Scenario:

  • IGNY8 schedules for "2025-12-01 10:00:00 UTC"
  • WordPress site timezone is "America/New_York" (UTC-5)
  • WordPress interprets as 10:00 AM New York time
  • Content publishes 5 hours later than intended

What's Missing:

  • Explicit timezone handling in payload
  • Timezone conversion logic in WordPress
  • Verification that scheduled time matches intent

GAP 8: All-or-Nothing Guarantees Missing

Problem: Content can be half-published (post exists but missing images/meta).

Current Flow:

1. wp_insert_post() → Success (post ID 1842)
2. Download featured image → FAILS
3. Assign categories → Success
4. Store SEO meta → Success
5. Report success to IGNY8 ✓

Result: Post published without featured image
IGNY8 thinks everything succeeded

What's Missing:

  • Transaction wrapper around entire publish operation
  • Failure detection for each sub-operation
  • Rollback mechanism if any step fails
  • Detailed error reporting (which step failed)

GAP 9: No Re-Publish Protection

Problem: If publish button clicked twice or Celery task runs twice, content duplicates.

Scenario:

  1. User clicks "Publish" in IGNY8
  2. Celery task queued
  3. User clicks "Publish" again (impatient)
  4. Second Celery task queued
  5. Both tasks run → 2 WordPress posts created for same content

What's Missing:

  • Task deduplication based on content_id + site_integration_id
  • Lock mechanism during publish
  • WordPress duplicate detection by _igny8_content_id before creating new post
  • Return existing post if already published (idempotent operation)

GAP 10: Publish Count Statistics Incomplete

Problem: You need counts by content type, but current system doesn't track this granularly.

What IGNY8 Needs:

class SiteIntegration(models.Model):
    # Current (missing):
    posts_published_count = models.IntegerField(default=0)
    pages_published_count = models.IntegerField(default=0)
    products_published_count = models.IntegerField(default=0)
    
    # Also need:
    categories_synced_count = models.IntegerField(default=0)
    tags_synced_count = models.IntegerField(default=0)
    sectors_synced_count = models.IntegerField(default=0)
    clusters_synced_count = models.IntegerField(default=0)
    
    last_publish_at = models.DateTimeField(null=True)
    total_sync_operations = models.IntegerField(default=0)

What's Missing:

  • WordPress needs to detect content type (post/page/product) and report it
  • WordPress needs to count new vs updated taxonomies and report
  • IGNY8 needs endpoints to receive these counts
  • Dashboard needs to display these statistics

GAP 11: Auto-Publish Scheduling Mechanism Unclear

Problem: Audit shows Celery runs every 5 minutes, but doesn't explain how scheduled publishing works.

Questions Unanswered:

  • If published_at is in future, does Celery skip it?
  • How does Celery know when to publish scheduled content?
  • Is there a separate queue for scheduled vs immediate?
  • What if scheduled time is missed (server down)?

What's Likely Missing:

  • Scheduled content query filter in Celery task
  • Time-based condition: published_at <= now()
  • Missed schedule handler (publish immediately if past due)
  • Different retry logic for scheduled vs immediate

GAP 12: Taxonomy Creation vs Assignment Not Clear

Problem: If category "Digital Marketing" doesn't exist in WordPress, what happens?

Scenario 1: Auto-Create (probably current):

  • WordPress creates category "Digital Marketing"
  • Assigns to post
  • Problem: Might create duplicates if slug differs ("digital-marketing" vs "digitalmarketing")

Scenario 2: Map to Existing:

  • WordPress looks up by name
  • If not found, uses fallback category
  • Problem: User needs to pre-create all categories

What's Missing:

  • Clear taxonomy reconciliation strategy
  • Slug normalization rules
  • Duplicate prevention logic
  • Fallback category configuration

GAP 13: Keywords Not Actually Published

Problem: Audit shows focus_keywords stored in meta, but WordPress doesn't use this field natively.

Current State:

  • IGNY8 sends: focus_keywords: ["SEO 2025", "ranking factors"]
  • WordPress stores: _igny8_focus_keywords meta
  • Nobody reads this field (unless custom code added)

What's Missing:

  • Integration with actual keyword tracking plugins (Yoast, RankMath, AIOSEO)
  • Mapping to plugin-specific meta fields
  • Fallback if no SEO plugin installed

Problem: Audit mentions "5 images max" for gallery but doesn't explain why or what happens to 6th image.

Questions:

  • Is this IGNY8 limit or WordPress plugin limit?
  • What happens if IGNY8 sends 10 images?
  • Are they silently dropped? Error thrown?
  • How does user know some images were skipped?

What's Missing:

  • Configurable gallery size limit
  • Clear error message if limit exceeded
  • Option to create separate gallery post/page for overflow

Implementation Plan (No Code)

Phase 1: Fix Critical Data Integrity Issues (Week 1-2)

1.1 Implement Atomic Transaction Pattern

  • Wrap entire publish operation in WordPress transaction
  • If ANY step fails → rollback everything
  • Delete post if created but subsequent operations failed
  • Report detailed failure info to IGNY8 (which step failed)

1.2 Add Pre-Flight Validation

Before attempting publish:

  • Verify author exists (by email)
  • Verify all image URLs accessible (HTTP HEAD request)
  • Verify required fields present (title, content)
  • Verify post type enabled in WordPress plugin settings
  • Return validation errors BEFORE creating anything

1.3 Implement Duplicate Prevention

  • Check if post with _igny8_content_id already exists
  • If exists → update instead of create (unless manual re-publish)
  • Add unique constraint in IGNY8: (content_id, site_integration_id) → only one publish task active at a time
  • Celery task deduplication by task signature

1.4 Add Post-Publish Verification

After WordPress reports "success":

  • Wait 5 seconds (let WordPress flush rewrites)
  • HTTP GET the permalink → expect 200
  • HTTP HEAD the featured image URL → expect 200
  • Query taxonomies assigned → expect count > 0
  • If verification fails → mark as "published_with_issues" status
  • Report verification results to IGNY8

Phase 2: Implement Publish Count Tracking (Week 2-3)

2.1 Extend IGNY8 Models

Add to SiteIntegration:

  • posts_published_count
  • pages_published_count
  • products_published_count
  • categories_synced_count
  • tags_synced_count
  • sectors_synced_count
  • clusters_synced_count
  • last_publish_at
  • total_sync_operations

2.2 Create IGNY8 Stats Endpoint

PUT /integrations/{site_id}/stats/increment/
Payload: {
    "content_type": "post",  // or "page", "product"
    "taxonomies_created": {
        "categories": 2,
        "tags": 5,
        "sectors": 1,
        "clusters": 1
    },
    "taxonomies_updated": {
        "categories": 0,
        "tags": 1,
        "sectors": 0,
        "clusters": 0
    },
    "published_at": "2025-11-29T10:15:30Z"
}

2.3 Update WordPress Plugin Response

After successful publish, WordPress must:

  • Detect post type (post/page/product)
  • Count new categories created vs existing assigned
  • Count new tags created vs existing assigned
  • Count new sectors created vs existing assigned
  • Count new clusters created vs existing assigned
  • Call IGNY8 stats endpoint with all counts
  • IGNY8 increments counters atomically

Phase 3: Implement Taxonomy Change Tracking (Week 3-4)

3.1 Add WordPress Hooks

Hook into:

  • set_object_terms (when taxonomies assigned/changed)
  • update_post_meta (when cluster/sector/keyword meta changed)
  • Filter by: post has _igny8_task_id meta (only track IGNY8-managed posts)

3.2 Create IGNY8 Taxonomy Update Endpoint

PUT /writer/tasks/{task_id}/taxonomies/
Payload: {
    "categories": [1, 2, 3],      // WordPress term IDs
    "tags": [5, 8, 12],
    "sectors": [2],
    "clusters": [7, 9],
    "updated_by": "wordpress_user_123",
    "updated_at": "2025-11-29T11:00:00Z"
}

3.3 Create IGNY8 Relationships Update Endpoint

PUT /writer/tasks/{task_id}/relationships/
Payload: {
    "cluster_id": 15,  // changed from 12
    "sector_id": 5,    // unchanged
    "keyword_ids": [1, 2, 3, 8],  // added keyword 8
    "updated_by": "wordpress_user_123",
    "updated_at": "2025-11-29T11:00:00Z"
}

3.4 Implement Debouncing

  • Don't sync every single taxonomy change immediately
  • Batch changes over 30-second window
  • Send one API call with all changes
  • Reduce API call volume by 95%

Phase 4: Separate Manual vs Auto-Publish Flows (Week 4-5)

4.1 Add publish_mode to API Payload

IGNY8 must send:

{
    "content_id": 42,
    "publish_mode": "manual",  // or "scheduled"
    "published_at": "2025-12-01T10:00:00Z",
    ...
}

4.2 Implement Different Logic

Manual Mode:

  • Ignore published_at timestamp (publish NOW)
  • If post already exists → force update (don't skip)
  • Return immediate feedback (synchronous within 5 seconds)
  • Retry aggressively (3 retries, 10 seconds apart)
  • Show user real-time progress

Scheduled Mode:

  • Respect published_at timestamp
  • If post already exists → skip (idempotent)
  • Queue for future execution
  • Retry conservatively (3 retries, 1 hour apart)
  • Don't notify user of each retry

4.3 Update Celery Task Query

# Current: publishes everything with status='completed'
pending_content = ContentPost.objects.filter(
    wordpress_sync_status='pending',
    published_at__isnull=False
)

# New: separate scheduled from immediate
immediate_content = ContentPost.objects.filter(
    wordpress_sync_status='pending',
    publish_mode='manual',
    published_at__isnull=False
)

scheduled_content = ContentPost.objects.filter(
    wordpress_sync_status='pending',
    publish_mode='scheduled',
    published_at__lte=now(),  # only if scheduled time reached
    published_at__isnull=False
)

Phase 5: Timezone Handling (Week 5)

5.1 Standardize on UTC Everywhere

  • IGNY8 always sends timestamps in UTC with explicit timezone: "2025-12-01T10:00:00Z"
  • WordPress plugin converts to site timezone for post_date
  • WordPress converts back to UTC when reporting to IGNY8
  • Never rely on implied timezones

5.2 Add Timezone to WordPress Response

{
    "success": true,
    "data": {
        "post_id": 1842,
        "post_date_utc": "2025-11-29T10:15:30Z",
        "post_date_site": "2025-11-29T05:15:30-05:00",
        "site_timezone": "America/New_York"
    }
}

5.3 Scheduled Publish Verification

  • IGNY8 stores: "Scheduled for 2025-12-01 10:00 UTC"
  • WordPress publishes at: "2025-12-01 05:00 EST" (correct)
  • WordPress reports back: "Published at 2025-12-01T10:00:00Z" (UTC)
  • IGNY8 verifies timestamp matches expected

Phase 6: Enhanced Error Reporting (Week 6)

6.1 Add Detailed Error Structure

{
    "success": false,
    "error": {
        "code": "FEATURED_IMAGE_DOWNLOAD_FAILED",
        "message": "Failed to download featured image",
        "step": "media_processing",
        "step_number": 3,
        "total_steps": 7,
        "details": {
            "image_url": "https://example.com/image.jpg",
            "http_status": 404,
            "error": "Not Found"
        },
        "recoverable": true,
        "retry_recommended": true
    }
}

6.2 Add Progress Reporting for Manual Publish

For manual publish, send progress updates:

POST /integrations/{site_id}/publish-progress/
{
    "task_id": 15,
    "step": "creating_post",
    "progress": 30,
    "message": "Creating WordPress post..."
}

Frontend shows real-time progress bar.


Phase 7: Taxonomy Reconciliation Strategy (Week 6-7)

7.1 Add Taxonomy Mapping Configuration

WordPress plugin settings:

  • Auto-create missing taxonomies: ON/OFF
  • Slug normalization: lowercase + hyphens
  • Duplicate detection: by slug (not name)
  • Fallback category: "Uncategorized" (if auto-create OFF and category not found)

7.2 Taxonomy Reconciliation Algorithm

For each category in IGNY8 payload:
    1. Normalize slug: "Digital Marketing" → "digital-marketing"
    2. Query WordPress by slug (not name)
    3. If found → use existing term ID
    4. If not found:
        a. If auto-create ON → create new term
        b. If auto-create OFF → use fallback category
    5. Assign term to post

7.3 Report Taxonomy Changes to IGNY8

{
    "taxonomies_processed": {
        "categories": {
            "requested": ["Digital Marketing", "SEO"],
            "created": ["SEO"],
            "existing": ["Digital Marketing"],
            "assigned": [1, 5]
        },
        "tags": {
            "requested": ["seo", "ranking"],
            "created": [],
            "existing": ["seo", "ranking"],
            "assigned": [8, 12]
        }
    }
}

Phase 8: SEO Plugin Integration (Week 7-8)

8.1 Detect Active SEO Plugin

WordPress plugin detects:

  • Yoast SEO
  • Rank Math
  • All in One SEO
  • SEOPress
  • (or none)

8.2 Map Focus Keywords to Plugin Fields

Yoast SEO:

  • _yoast_wpseo_focuskw = first keyword
  • _yoast_wpseo_keywordsynonyms = remaining keywords (comma-separated)

Rank Math:

  • rank_math_focus_keyword = first keyword
  • Additional keywords stored in JSON meta

All in One SEO:

  • _aioseo_keywords = comma-separated list

No Plugin:

  • Store in _igny8_focus_keywords (current behavior)
  • Optional: Generate simple meta keywords tag

8.3 Report SEO Plugin Status to IGNY8

{
    "seo_plugin": {
        "active": "yoast",
        "version": "22.0",
        "keywords_supported": true,
        "focus_keyword_set": true
    }
}

WordPress plugin settings:

  • Max gallery images: 5 (default)
  • Overflow behavior:
    • "Skip extra images" (current)
    • "Create separate gallery post"
    • "Add to post content as image grid"

9.2 Handle Overflow Images

If IGNY8 sends 10 images but limit is 5:

Option A: Skip:

  • Use first 5
  • Report to IGNY8: "gallery_images_skipped": 5

Option B: Create Separate Post:

  • Create new post: "{Original Title} - Gallery"
  • Attach images 6-10
  • Link from original post
  • Report to IGNY8: "gallery_overflow_post_id": 1843

Option C: Inline Grid:

  • Append HTML grid to post content
  • All 10 images in post body
  • Report to IGNY8: "gallery_images_inline": 10

Phase 10: Monitoring & Dashboard (Week 9)

10.1 IGNY8 Dashboard Enhancements

Display per site:

  • Total Published: Posts (X) | Pages (Y) | Products (Z)
  • Taxonomies Synced: Categories (A) | Tags (B) | Sectors (C) | Clusters (D)
  • Last Published: 2 hours ago
  • Publish Success Rate: 98.5% (last 30 days)
  • Average Publish Time: 3.2 seconds
  • Pending: 5 scheduled for today

10.2 WordPress Plugin Dashboard

Display:

  • IGNY8 Posts: 142 published | 5 pending
  • Last Sync: 10 minutes ago
  • Connection Status: Connected ✓
  • Recent Activity:
    • 10:15 AM - Published "SEO Guide 2025" (post)
    • 10:05 AM - Published "About Us" (page)
    • 09:50 AM - Synced 3 categories

10.3 Add Health Check Endpoint

GET /wp-json/igny8/v1/health
Response:
{
    "status": "healthy",
    "checks": {
        "api_connection": "ok",
        "database": "ok",
        "media_uploads": "ok",
        "taxonomy_creation": "ok"
    },
    "stats": {
        "posts_managed": 142,
        "last_publish": "2025-11-29T10:15:30Z",
        "disk_space": "15GB free"
    }
}

Call from IGNY8 every 5 minutes to detect issues early.


Summary: What Actually Needs to Change

Backend (IGNY8 Django) Changes:

  1. Add Models Fields:

    • publish_mode to ContentPost ('manual' or 'scheduled')
    • Publish count fields to SiteIntegration
    • Taxonomy sync count fields
  2. Add API Endpoints:

    • PUT /integrations/{id}/stats/increment/ (receive counts from WP)
    • PUT /writer/tasks/{id}/taxonomies/ (receive taxonomy changes from WP)
    • PUT /writer/tasks/{id}/relationships/ (receive cluster/sector changes from WP)
  3. Update Celery Task:

    • Add pre-flight validation
    • Separate scheduled vs manual queries
    • Add duplicate prevention
    • Add timezone handling
    • Improve error reporting
  4. Update API Call to WordPress:

    • Send publish_mode flag
    • Send explicit UTC timezone
    • Handle detailed error responses
    • Process verification results

Frontend (IGNY8 Vue/React) Changes:

  1. Manual Publish Button:

    • Show real-time progress (if WordPress sends updates)
    • Show detailed success message with link to WP post
    • Show detailed error message if fails (which step failed)
  2. Dashboard Stats:

    • Display publish counts by content type
    • Display taxonomy sync counts
    • Display last publish timestamp
    • Display success rate graph
  3. Scheduled Publish UI:

    • Datetime picker with timezone display
    • "Schedule for: Dec 1, 2025 10:00 AM UTC (5:00 AM your time)"
    • List of scheduled publications
    • Ability to cancel scheduled publish

WordPress Plugin Changes:

  1. Core Publish Function:

    • Wrap in transaction (all-or-nothing)
    • Add pre-flight validation
    • Add duplicate detection
    • Add post-publish verification
    • Handle publish_mode flag differently
  2. Add Taxonomy Hooks:

    • Detect changes to categories/tags/sectors/clusters
    • Batch changes over 30 seconds
    • Call IGNY8 API to sync changes
  3. Add Stats Tracking:

    • Count content types published
    • Count taxonomies created vs assigned
    • Call IGNY8 stats endpoint after each publish
  4. Settings Page:

    • Taxonomy auto-create ON/OFF
    • Taxonomy fallback category selector
    • Gallery image limit (slider: 1-20)
    • Gallery overflow behavior (dropdown)
    • SEO plugin integration status
  5. Response Format:

    • Add verification results
    • Add taxonomy processing details
    • Add publish counts
    • Add timezone info

Testing Strategy

1. Atomic Transaction Tests

  • Publish with invalid image URL → entire operation should fail, no post created
  • Publish with invalid author → entire operation should fail
  • Publish with SEO plugin disabled → post created, SEO meta stored anyway

2. Duplicate Prevention Tests

  • Click publish button twice rapidly → only 1 post created
  • Celery task runs while manual publish in progress → only 1 post created
  • Re-publish same content → update existing post, don't create new

3. Timezone Tests

  • Schedule for "Dec 1, 2025 10:00 UTC" from timezone UTC+5 → publishes at correct time
  • WordPress in timezone "America/New_York" → post_date stored correctly in local time
  • IGNY8 receives post_date_utc → matches scheduled time exactly

4. Taxonomy Sync Tests

  • Add category in WordPress → IGNY8 receives update within 30 seconds
  • Remove tag in WordPress → IGNY8 receives update
  • Change cluster via custom field → IGNY8 receives update
  • Change multiple taxonomies at once → IGNY8 receives 1 batched update

5. Count Tracking Tests

  • Publish 1 post → SiteIntegration.posts_published_count increments by 1
  • Publish 1 page → SiteIntegration.pages_published_count increments by 1
  • Create 2 new categories → SiteIntegration.categories_synced_count increments by 2
  • Update post (no new taxonomies) → counts don't change

6. Manual vs Scheduled Tests

  • Manual publish → immediate execution, ignores published_at
  • Scheduled publish → waits until published_at time
  • Manual re-publish of scheduled content → publishes immediately, overrides schedule

Implementation Priority

Critical (Do First):

  1. Atomic transactions (Phase 1.1)
  2. Duplicate prevention (Phase 1.3)
  3. Publish count tracking (Phase 2)
  4. Manual vs scheduled separation (Phase 4)

High Priority:

  1. Timezone handling (Phase 5)
  2. Taxonomy change tracking (Phase 3)
  3. Enhanced error reporting (Phase 6)

Medium Priority:

  1. Taxonomy reconciliation (Phase 7)
  2. SEO plugin integration (Phase 8)
  3. Gallery improvements (Phase 9)

Low Priority:

  1. Dashboard enhancements (Phase 10)

This plan focuses on real functional gaps that affect data integrity, user experience, and system reliability. No cosmetics, just critical infrastructure improvements.