Skip to content

[#320] Fix backfill: missing title, silent data loss, cron auth #322

@realproject7

Description

@realproject7

Context

Audit #320 identified three confirmed issues in the backfill cron (src/app/api/cron/backfill/route.ts), agreed on by all 5 reviewers.

Task 1: Add missing plot title (E3)

processPlotChained() (line 261) destructures title from event args but never writes it to the DB row. The direct indexer (src/app/api/index/plot/route.ts:118) correctly writes title: title || "".

Fix: Add title: title || "" to the PlotInsert row in processPlotChained() around line 270.

Task 2: Log failed events instead of silently skipping (E6, E7)

When IPFS content can't be fetched or hash doesn't match, processPlotChained() and processStorylineCreated() silently return. The cursor still advances to toBlock, permanently skipping those events.

Fix:

  1. Create a backfill_failures Supabase table: (id, tx_hash, log_index, block_number, event_name, storyline_id, reason, created_at)
  2. When IPFS fetch fails or hash mismatches, insert a row into backfill_failures instead of silently returning
  3. Count these as errors in the response JSON
  4. Cursor can still advance (to avoid infinite loops), but failures are now visible and recoverable

Migration file needed: supabase/migrations/XXXXXX_backfill_failures.sql

Task 3: Fail closed on missing CRON_SECRET in production (D2)

verifyCron() returns true when CRON_SECRET is not set. In production, this means anyone can trigger backfill.

Fix:

function verifyCron(req: Request): boolean {
  const secret = process.env.CRON_SECRET;
  if (!secret) {
    return process.env.NODE_ENV !== "production";
  }
  const authHeader = req.headers.get("authorization");
  return authHeader === `Bearer ${secret}`;
}

Acceptance Criteria

  • Backfilled plots include title field matching direct indexer behavior
  • Failed IPFS fetches/hash mismatches are logged to backfill_failures table
  • Backfill response JSON includes skipped event count
  • verifyCron() rejects requests when CRON_SECRET is unset in production
  • Migration file for backfill_failures table included
  • npm run build and npm run typecheck pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/T3Assigned to T3 builder agentbugSomething isn't workingphase/1-contentPhase 1: Content Pipeline

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions