How-To: Common Team Questions
How do I add a new ERP integration?
Section titled βHow do I add a new ERP integration?β- Implement the ERP service interface in
apps/webapp/src/services/erp/implementations/ - Register it in
ERPSourceFactory - Add a corresponding type-declaration stub in
apps/ts-temporal-worker/src/webapp-types/ - If the ERP needs Python-side sync (for the Dagster pipeline), add a source
in
apps/dagster/erp_pipeline/sources/ - Add it to the
ERPTypeenum in the shared packages
Do not add ERP-specific branching anywhere outside the factory pattern.
How do I force a manual ERP sync?
Section titled βHow do I force a manual ERP sync?βUse the canonical admin endpoints (not the legacy Trigger.dev ones):
POST /api/erp/force-syncβ force a full ERP catalog syncPOST /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.
How do I add a new feature flag?
Section titled βHow do I add a new feature flag?β- Create the flag in Flagsmith (staging first, then production)
- In
apps/dagster/erp_pipeline/config.py, add aget_<flag_name>()function using the existingget_iceberg_catalog_enabled()as a template β it falls back to env vars for local dev - Gate your code on the function, not raw Flagsmith calls
How do I add a new API route?
Section titled βHow do I add a new API route?βExtend BaseAPIHandler in apps/webapp/src/lib/api/base-handler.ts.
- Use
requireAuthfor user-facing routes - Use
requireAdminfor admin-only routes - All routes automatically get rate limiting, bot blocking, and default-deny auth
How do I trigger a Temporal workflow from the webapp?
Section titled βHow do I trigger a Temporal workflow from the webapp?β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/.
How do I run the Dagster pipeline locally?
Section titled βHow do I run the Dagster pipeline locally?βcd apps/dagsteruv run dagster devThe feature flag mediator (config.py) reads from env vars in local dev,
so set ICEBERG_CATALOG_ENABLED=true etc. to test flag-gated paths.
How do I add a column to the Iceberg schema?
Section titled βHow do I add a column to the Iceberg schema?β- Add to
FIELD_ORDERinapps/dagster/erp_pipeline/utils/schema_registry.pyfirst - Add to the transformer(s) that produce that column
- The canonical field order must be maintained β schema_registry.py is the single source of truth
Where do background jobs live?
Section titled βWhere do background jobs live?β- 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
How do I debug a stuck Temporal workflow?
Section titled βHow do I debug a stuck Temporal workflow?β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}.