factflow-foundation
Shared configuration framework, path resolution, and observability primitives used by every other factflow-* package.
Tier and role
Section titled “Tier and role”- Tier: shared service (root of the shared tier; only depends on
factflow-protocols) - Import name:
factflow_foundation - Source:
backend/packages/factflow-foundation/
Virtually every backend package imports something from here. Users don’t import it directly — they consume it transitively through whatever shared service or workflow they plug into.
Context
Section titled “Context”Three concerns, one package:
- Configuration — typed Pydantic-settings config with environment-aware loading, dependency-injected
Configobject. Explicitly no singletons; all access goes throughget_config()/override_config(). - Path resolution — deterministic keys and paths for executions, stages, and artefacts.
ExecutionPathResolveris the canonical way to derive a storage key from an execution + route + stage + message. - Observability — correlation-id propagation across async contexts, structured logging helpers, message-flow tracking.
These concerns share enough utility (path and correlation both lean on UUIDs; config drives logging) that combining them into one package avoids tight coupling in downstream packages. Splitting later is cheap if needed.
Public API
Section titled “Public API”Two subpackages, both re-exported via their own __init__.
Configuration (factflow_foundation.configuration)
Section titled “Configuration (factflow_foundation.configuration)”from factflow_foundation.configuration import ( Config, # the root config object (DI-injected) ConfigProtocol, # the protocol the Config satisfies AppConfig, # app-level settings DatabaseConfig, LoggingConfig, PathConfig, get_config, # lazy accessor (uses override if set) set_config, # explicit set — prod path override_config, # test-scoped override reset_config, # test teardown)No import-time side effects. Config is loaded when get_config() first runs or when set_config() is called explicitly. Tests use override_config() with a context manager.
Shared utilities (factflow_foundation.shared)
Section titled “Shared utilities (factflow_foundation.shared)”from factflow_foundation.shared import ( # Correlation + logging correlation_context, # async context-manager that propagates a correlation id get_correlation_id, set_correlation_id, CorrelationIdFilter, # logging.Filter that injects the correlation id configure_correlation_logging, get_contextual_logger,
# Message-flow tracing MessageFlow, track_message_flow,
# Path resolution ExecutionPathResolver, # build storage keys from execution + route + stage PipelineStage, # enum of canonical stage names
# Storage scope StorageContext,)The correlation helpers are imported by factflow-lineage and every adapter that logs. ExecutionPathResolver is the contract every storage-writing adapter uses to derive its key.
Dependencies
Section titled “Dependencies”- Runtime:
pydantic,pydantic-settings,python-dotenv,pyyaml,tomli,colorlog,uuid-utils - Workspace:
factflow-protocols - External services: none
Testing
Section titled “Testing”Tests live at backend/packages/factflow-foundation/tests/. The fixtures for config override patterns are reusable — downstream package tests that need a config override should import the helpers from here rather than roll their own.
Related
Section titled “Related”factflow-protocols—ConfigProtocol+ path-related types are defined as contracts therefactflow-lineage— consumes correlation helpers for lineage recordsfactflow-engine— consumes path resolver for stage storage keys