Skip to content

Enriching publisher plugin error capture & unify its database setup and migration paths#35

Open
Jurij89 wants to merge 3 commits intomainfrom
fix/publisher-plugin-error-message
Open

Enriching publisher plugin error capture & unify its database setup and migration paths#35
Jurij89 wants to merge 3 commits intomainfrom
fix/publisher-plugin-error-message

Conversation

@Jurij89
Copy link
Contributor

@Jurij89 Jurij89 commented Feb 23, 2026

Summary

This PR adds structured error details to publishing attempts and unifies the publisher plugin's database management under Drizzle migrations as the single source of truth.

Structured error details

  • New error_details JSON column on publishing_attempts table for capturing rich error context from DKG publish failures
  • New errorUtils.ts utility for extracting structured error info (error type, message, stack traces, nested causes)
  • PublishingService and QueueService updated to store and propagate structured error details through the publishing pipeline

Unified database migrations

  • Auto-migration on startup — Plugin runs bootstrapMigrationJournal() + runMigrations() during initialization. Users pulling updates get schema changes automatically with zero manual steps.
  • Bootstrap guard for legacy databases — Databases created by the old setup.js (no __drizzle_migrations table) are detected and have their migration journal seeded so Drizzle can take over without re-running CREATE TABLE.
  • setup.js uses Drizzle migrations — Raw DDL (DROP + CREATE TABLE x6) replaced with migrate(). Mode 1 (Fresh) drops all tables then runs migrations. Mode 2 (Update) applies only pending migrations.
  • FK incompatibility fix — Migration 0001 changed PKs from char(36) to serial (BIGINT UNSIGNED) but FK columns to int (signed). MySQL requires exact type match. Fixed by using int AUTO_INCREMENT for PKs and explicitly dropping/re-adding FK constraints around column type changes.
  • Column renameprivate_key_encryptedprivate_key (folded into migration 0002 alongside error_details)
  • Removed migrate.js — No longer needed since migrations auto-run on startup and setup.js handles all setup paths.

Setup script improvements

  • Reordered modes: 1 = Fresh setup (with warning about table deletion), 2 = Update, 3 = Add wallets only
  • Password input is now actually hidden during entry
  • Mode 2 (Update) correctly overwrites config files
  • Renamed "OT-Node URL" to "DKG Engine URL"
  • Removed inaccurate messaging (encryption claim, Docker reference, Claude-specific wording)

Files changed

File Change Why
src/services/errorUtils.ts New Structured error extraction from DKG publish failures
src/services/PublishingService.ts Modified Stores structured error_details on failed attempts
src/services/QueueService.ts Modified Passes error details through queue processing
src/services/AssetService.ts Modified Error detail propagation
src/database/bootstrap.ts New Seeds migration journal for legacy setup.js databases
src/database/index.ts Modified Fixed migration folder path for tsup flat bundle; dedicated connection
src/database/schema.ts Modified serialint().autoincrement() for PKs; private_key_encryptedprivate_key
src/database/migrations/0001_*.sql Modified Drop/re-add FKs around MODIFY COLUMN; serialint AUTO_INCREMENT
src/database/migrations/0002_*.sql New Adds error_details column, renames private_key_encryptedprivate_key
src/database/migrations/meta/* Modified/New Journal entry + snapshot for migration 0002
src/database/migrations/20250905_*.sql Deleted Orphan not in journal (rename folded into 0002)
src/services/index.ts Modified Runs bootstrap + migrations on plugin startup
src/services/WalletService.ts Modified Removed stale privateKeyEncrypted remapping
setup.js Modified Replaced raw DDL with migrate(), added bootstrap guard, UX fixes, reordered modes
migrate.js Deleted Redundant — migrations auto-run on startup
package.json Modified Updated dkg.js dependency
package-lock.json Modified Lockfile update

All paths relative to packages/plugin-dkg-publisher/ unless otherwise noted.

Test plan

  • Fresh install (Mode 1): Drop database → run setup → verify tables created with error_details column and private_key column
  • Existing setup.js user (no journal): Old database without __drizzle_migrations → start plugin → verify bootstrap seeds journal + applies pending migrations
  • Mode 2 (Update): Run setup on existing config → verify config files overwritten, only pending migrations applied, no data loss
  • Publishing with error details: Trigger a publish failure → verify error_details JSON is populated in publishing_attempts
  • Idempotency: Start plugin twice → verify no errors on second startup
  • Dev mode: npm run dev → verify auto-migration runs on startup
  • Password input: Run setup → verify DB password is not echoed to terminal
  • Build: npm run build passes in packages/plugin-dkg-publisher

🤖 Generated with Claude Code

Jurij Skornik and others added 2 commits February 23, 2026 21:41
- Make Drizzle migrations the single source of truth, replacing dual
  raw DDL + Drizzle paths in setup.js
- Auto-run migrations on plugin startup (zero manual steps for updates)
- Add bootstrap guard for databases created by old setup.js (seeds
  __drizzle_migrations journal so Drizzle can take over)
- Fix migration 0001 FK incompatibility: change PKs from serial
  (BIGINT UNSIGNED) to int AUTO_INCREMENT to match int FK columns
- Add 0002 migration for error_details column and private_key rename
- Fix migration folder path resolution for tsup flat bundle output
- Improve setup.js: hide password input, fix Mode 1 config overwrite,
  replace raw DDL with migrate(), update wording
- Add structured error details to publishing attempts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Mode 1 is now "Start fresh" with a warning about table deletion
- Mode 2 is now "Update existing configuration"
- Mode 3 remains "Add wallets only"
@Jurij89 Jurij89 changed the title Unify publisher plugin database setup and migration paths Enriching publisher plugin error capture & unify its database setup and migration paths Feb 23, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the DKG publisher plugin by persisting structured error context for failed publishing attempts and consolidating database setup/migration flows around Drizzle migrations (including bootstrapping legacy databases without a migration journal).

Changes:

  • Add error_details JSON support end-to-end (DB column + error serialization + propagation through publishing/queue pipeline).
  • Introduce migration-journal bootstrapping for legacy (setup.js raw-DDL) databases and run migrations on plugin startup.
  • Update schema/migrations to use int AUTO_INCREMENT PKs (and FK handling) and rename private_key_encryptedprivate_key; refactor setup.js to use Drizzle migrations.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/plugin-dkg-publisher/src/services/index.ts Runs migration bootstrap + migrations during service initialization.
packages/plugin-dkg-publisher/src/services/errorUtils.ts New helper to serialize errors into structured JSON for persistence.
packages/plugin-dkg-publisher/src/services/QueueService.ts Propagates/serializes errorDetails into failed publishing attempts.
packages/plugin-dkg-publisher/src/services/PublishingService.ts Returns structured error details from DKG publish failures.
packages/plugin-dkg-publisher/src/services/AssetService.ts Extends attempt-update payload to include errorDetails.
packages/plugin-dkg-publisher/src/services/WalletService.ts Removes legacy remapping for privateKeyEncryptedprivateKey.
packages/plugin-dkg-publisher/src/database/bootstrap.ts Bootstraps __drizzle_migrations for legacy DBs so Drizzle can take over.
packages/plugin-dkg-publisher/src/database/index.ts Runs migrations via a dedicated connection and updates migrations folder path.
packages/plugin-dkg-publisher/src/database/schema.ts Switches PKs to int().autoincrement(), adds error_details JSON, renames private_key.
packages/plugin-dkg-publisher/src/database/migrations/0001_amused_dexter_bennett.sql Adjusts PK/FK types and drops/re-adds FKs around column changes.
packages/plugin-dkg-publisher/src/database/migrations/0002_add_error_details.sql Adds error_details column and renames private_key_encryptedprivate_key.
packages/plugin-dkg-publisher/src/database/migrations/meta/_journal.json Adds journal entry for migration 0002.
packages/plugin-dkg-publisher/src/database/migrations/meta/0002_snapshot.json Snapshot update for migration 0002 state.
packages/plugin-dkg-publisher/setup.js Replaces raw DDL with Drizzle migrations; adds legacy bootstrap and UX improvements.
packages/plugin-dkg-publisher/migrate.js Removes standalone migration script.
package.json Updates dependency set (including dkg.js).
package-lock.json Lockfile refresh reflecting dependency changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +38
function sanitize(value: unknown): unknown {
if (value === null || value === undefined) return value;
if (typeof value === "bigint") return value.toString();
if (typeof value === "function") return undefined;
if (typeof value !== "object") return value;

if (seen.has(value as object)) return "[Circular]";
seen.add(value as object);

if (Array.isArray(value)) {
return value.map(sanitize);
}

const result: Record<string, unknown> = {};
for (const key of Object.keys(value as Record<string, unknown>)) {
if (key === "stack") continue;
result[key] = sanitize((value as Record<string, unknown>)[key]);
}
return result;
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serializeErrorDetails claims to capture useful Error properties, but nested Error instances (e.g. via cause) are currently sanitized as plain objects, which drops non-enumerable fields like name/message (and you also always skip stack). This means nested causes won’t be meaningfully captured. Consider special-casing Error inside sanitize (and/or aligning the docstring) so nested errors retain name/message (and optionally a truncated stack) while still protecting against cycles.

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +3
import { Database, createDatabase, runMigrations } from "../database";
import { bootstrapMigrationJournal } from "../database/bootstrap";
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Database is imported here but never used, which will fail linting/TS settings that disallow unused imports. Remove it or use it for an explicit type annotation where needed.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants