Skip to content

How-To: Common Team Questions

  1. Implement the ERP service interface in apps/webapp/src/services/erp/implementations/
  2. Register it in ERPSourceFactory
  3. Add a corresponding type-declaration stub in apps/ts-temporal-worker/src/webapp-types/
  4. If the ERP needs Python-side sync (for the Dagster pipeline), add a source in apps/dagster/erp_pipeline/sources/
  5. Add it to the ERPType enum in the shared packages

Do not add ERP-specific branching anywhere outside the factory pattern.

Use the canonical admin endpoints (not the legacy Trigger.dev ones):

  • POST /api/erp/force-sync β€” force a full ERP catalog sync
  • POST /api/erp/force-image-sync β€” force image sync only

The legacy /api/trigger/force-erp-sync still works as a compat shim but will be removed. Use the new endpoints.

  1. Create the flag in Flagsmith (staging first, then production)
  2. In apps/dagster/erp_pipeline/config.py, add a get_<flag_name>() function using the existing get_iceberg_catalog_enabled() as a template β€” it falls back to env vars for local dev
  3. Gate your code on the function, not raw Flagsmith calls

Extend BaseAPIHandler in apps/webapp/src/lib/api/base-handler.ts.

  • Use requireAuth for user-facing routes
  • Use requireAdmin for admin-only routes
  • All routes automatically get rate limiting, bot blocking, and default-deny auth

Use the helpers in apps/webapp/src/lib/temporal.ts β€” don’t create new Temporal client instances. For PDF extraction:

import { startPDFExtractionWorkflow } from '@/lib/temporal';
const { workflowId } = await startPDFExtractionWorkflow(documentId, { ... });

For ERP order submission, use the starters in apps/webapp/src/temporal/starters/.

Terminal window
cd apps/dagster
uv run dagster dev

The feature flag mediator (config.py) reads from env vars in local dev, so set ICEBERG_CATALOG_ENABLED=true etc. to test flag-gated paths.

  1. Add to FIELD_ORDER in apps/dagster/erp_pipeline/utils/schema_registry.py first
  2. Add to the transformer(s) that produce that column
  3. The canonical field order must be maintained β€” schema_registry.py is the single source of truth
  • Temporal (apps/temporal-worker, apps/ts-temporal-worker): durable workflows (PDF extraction, ERP submission, billing, email routing)
  • Dagster (apps/dagster): scheduled syncs, dbt runs, catalog jobs
  • Do not use Trigger.dev β€” it’s retired

Check the Temporal UI (ask David for the URL). Workflows that are stuck in QUOTE_PENDING or processing usually mean an activity failed after retries exhausted. Look at the workflow history for the specific error.

For PDF extraction specifically, the workflow ID is pdf-extraction-{documentId}.