Files
zeekayandHanzo Dev fad96e267f no hogs: the root config, the tooling, and the receiver baseline
.stamphog/ was a config directory at the repo root — policy.yml,
review-guidance.md — read by the PR review agent. It is .stamp/ now, and the 34
files that name it follow: the workflows, tools/pr-approval-agent, tach.toml,
the sandbox Dockerfile, bin/debrand.

One behaviour change worth naming rather than burying: the agent finds its own
previous PR comment by an HTML marker, `<!-- stamphog:v1 ... -->`, and that
marker is now `<!-- stamp:v1 ... -->`. Open PRs will get one new comment instead
of an edit, once, and then match again.

insights/test/setup_receivers_baseline.txt records registered signal receivers
by module path, so it names products.review.backend now.

stamphog: zero occurrences anywhere in the tree. review_hog: only inside
migration files, whose names are their identity in django_migrations.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-09 10:21:41 -07:00

1239 lines
27 KiB
TOML

layers = [
"modules",
]
exclude = [
"**/*__pycache__",
"**/*egg-info",
"docs",
"tests",
# Eval trees are dev/CI-only tooling (same class as `tests`): the harness orchestrates
# many products by design, and product-owned suites under products/*/evals import the
# harness contracts, so neither fits the production dependency graph.
"products/insights_ai/eval_harness",
"products/*/evals",
]
source_roots = [
".",
]
[[modules]]
path = "<root>"
depends_on = [
]
layer = "modules"
[[modules]]
path = "common.insightsql_parser"
depends_on = []
layer = "modules"
utility = true
[[modules]]
path = "common.scriptvm.python"
depends_on = [
"insights",
]
layer = "modules"
utility = true
[[modules]]
path = "ee"
depends_on = [
"products.cohorts",
"insights",
"products.actions",
"products.alerts",
"products.cdp",
"products.conversations",
"products.customer_analytics",
"products.dashboards",
"products.data_modeling",
"products.data_tools",
"products.demo",
"products.error_tracking",
"products.event_definitions",
"products.experiments",
"products.feature_flags",
"products.ai_observability",
"products.mcp_store",
"products.notebooks",
"products.insights_ai",
"products.product_analytics",
"products.replay",
"products.replay_vision",
"products.skills",
"products.revenue_analytics",
"products.surveys",
"products.tasks",
"products.business_knowledge",
"products.user_interviews",
"products.warehouse_sources",
"products.exports",
]
layer = "modules"
[[modules]]
path = "insights"
depends_on = [
"products.cohorts",
"ee",
"products.access_control",
"products.analytics_platform",
"products.approvals",
"products.batch_exports",
"products.business_knowledge",
"products.canvas",
"products.cdp",
"products.conversations",
"products.customer_analytics",
"products.dashboards",
"products.data_catalog",
"products.data_modeling",
"products.data_warehouse",
"products.demo",
"products.early_access_features",
"products.endpoints",
"products.engineering_analytics",
"products.error_tracking",
"products.event_definitions",
"products.experiments",
"products.feature_flags",
"products.growth",
"products.legal_documents",
"products.links",
"products.ai_observability",
"products.logs",
"products.managed_warehouse",
"products.marketing_analytics",
"products.messaging",
"products.metrics",
"products.notebooks",
"products.notifications",
"products.insights_ai",
"products.product_analytics",
"products.product_tours",
"products.pulse",
"products.reminders",
"products.replay",
"products.replay_vision",
"products.revenue_analytics",
"products.review",
"products.signals",
"products.skills",
"products.slack_app",
"products.stamp",
"products.streamlit_apps",
"products.surveys",
"products.tasks",
"products.tracing",
"products.user_interviews",
"products.mcp_analytics",
"products.web_analytics",
"products.workflows",
"products.actions",
"products.alerts", "products.warehouse_sources", "products.data_tools", "products.exports", "products.annotations",
]
layer = "modules"
[[modules]]
path = "products.actions"
depends_on = [
"products.cohorts",
"insights",
"products.cdp",
"products.experiments",
"products.feature_flags",
"products.product_analytics",
]
layer = "modules"
[[modules]]
path = "products.ai_gateway"
depends_on = ["insights"]
layer = "modules"
[[modules]]
path = "products.alerts"
depends_on = [
"ee",
"insights",
"products.cdp",
"products.product_analytics",
]
layer = "modules"
[[modules]]
path = "products.analytics_platform"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.approvals"
depends_on = [
"ee",
"insights",
"products.feature_flags",
"products.notifications",
]
layer = "modules"
[[modules]]
path = "products.batch_exports"
depends_on = [
"ee",
"insights",
"products.notifications",
]
layer = "modules"
[[modules]]
path = "products.cdp"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.actions",
"products.batch_exports",
]
layer = "modules"
[[modules]]
path = "products.cohorts"
depends_on = [
"products.actions",
"insights",
]
layer = "modules"
[[modules]]
path = "products.conversations"
depends_on = [
"ee",
"insights", "products.tasks", "products.business_knowledge", "products.warehouse_sources", "products.customer_analytics",
]
layer = "modules"
[[modules]]
path = "products.core_events"
depends_on = []
layer = "modules"
[[modules]]
path = "products.dashboards"
depends_on = [
"ee",
"insights",
"products.alerts",
"products.ai_observability",
"products.error_tracking",
"products.experiments",
"products.feature_flags",
"products.logs",
"products.mcp_analytics",
"products.notifications",
"products.product_analytics",
"products.surveys",
]
layer = "modules"
[[modules]]
path = "products.data_modeling"
depends_on = [
"insights",
"products.data_tools",
"products.data_warehouse",
"products.revenue_analytics",
"products.warehouse_sources",
]
layer = "modules"
[[modules]]
path = "products.data_tools"
depends_on = ["insights"]
layer = "modules"
[[modules]]
path = "products.games"
depends_on = []
layer = "modules"
[[modules]]
path = "products.groups"
depends_on = []
layer = "modules"
[[modules]]
path = "products.ingestion"
depends_on = []
layer = "modules"
[[modules]]
path = "products.integrations"
depends_on = []
layer = "modules"
[[modules]]
path = "products.persons"
depends_on = []
layer = "modules"
[[modules]]
path = "products.session_replay"
depends_on = []
layer = "modules"
[[modules]]
path = "products.session_summaries"
depends_on = []
layer = "modules"
[[modules]]
path = "products.subscriptions"
depends_on = []
layer = "modules"
[[modules]]
path = "products.support"
depends_on = []
layer = "modules"
[[modules]]
path = "products.toolbar"
depends_on = []
layer = "modules"
[[modules]]
path = "products.warehouse_sources"
depends_on = [
"ee",
"insights",
"products.cdp",
"products.data_modeling",
"products.data_tools",
"products.data_warehouse",
"products.notifications",
"products.insights_ai",
"products.revenue_analytics",
"products.warehouse_sources_queue",
"products.workflows",
"products.managed_warehouse",
]
layer = "modules"
[[modules]]
path = "products.data_warehouse"
depends_on = [
"ee",
"insights",
"products.cdp",
"products.data_modeling",
"products.revenue_analytics", "products.warehouse_sources", "products.data_tools", "products.batch_exports",
"products.warehouse_sources_queue",
"products.managed_warehouse",
]
layer = "modules"
[[modules]]
path = "products.demo"
depends_on = [
"insights",
"products.actions",
"products.cohorts",
"products.dashboards",
"products.data_tools",
"products.endpoints",
"products.error_tracking",
"products.event_definitions",
"products.experiments",
"products.feature_flags",
"products.product_analytics",
"products.warehouse_sources",
]
layer = "modules"
[[modules]]
path = "products.early_access_features"
depends_on = [
"insights",
"ee",
"products.feature_flags",
]
layer = "modules"
[[modules]]
path = "products.endpoints"
depends_on = [
"insights",
"products.data_modeling",
"products.data_warehouse",
"products.product_analytics",
"products.signals", "products.warehouse_sources",
"products.managed_warehouse",
]
layer = "modules"
[[modules]]
path = "products.error_tracking"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.cdp",
"products.notifications",
"products.signals",
"products.warehouse_sources",
]
layer = "modules"
[[modules]]
path = "products.event_definitions"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.experiments"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.access_control",
"products.actions",
"products.approvals",
"products.ai_observability",
"products.analytics_platform",
"products.data_tools",
"products.event_definitions",
"products.feature_flags",
"products.notifications",
"products.product_tours",
"products.surveys",
"products.tasks",
"products.warehouse_sources",
]
layer = "modules"
[[modules]]
path = "products.feature_flags"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.approvals",
"products.dashboards",
"products.early_access_features",
"products.experiments",
"products.product_analytics",
"products.product_tours",
"products.surveys",
]
layer = "modules"
[[modules]]
path = "products.growth"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.links"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.live_debugger"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.ai_observability"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.dashboards",
"products.exports",
"products.workflows",
]
layer = "modules"
[[modules]]
# Vestigial app — only retains the migration history under the llm_analytics
# Django app label. All models and code live under products.ai_observability now.
# Historical migration files reference insights.models.utils etc.; allowed because
# they're frozen history, not new code.
path = "products.llm_analytics"
depends_on = ["insights"]
layer = "modules"
[[modules]]
path = "products.logs"
depends_on = [
"insights",
"products.alerts",
"products.cdp",
"products.exports",
"products.signals",
]
layer = "modules"
[[modules]]
path = "products.managed_migrations"
depends_on = [
"insights",
"products.batch_exports",
]
layer = "modules"
[[modules]]
path = "products.mcp_analytics"
depends_on = [
"insights",
"products.dashboards",
]
layer = "modules"
[[modules]]
path = "products.mcp_store"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.messaging"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.metrics"
depends_on = ["insights"]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.api.*",
]
from = [
"products.metrics",
]
[[modules]]
path = "products.notebooks"
depends_on = [
"ee",
"insights",
"products.product_analytics",
"products.tasks",
]
layer = "modules"
[[modules]]
path = "products.pulse"
depends_on = [
"ee",
"insights",
"products.ai_observability",
"products.alerts",
"products.annotations",
"products.dashboards",
"products.experiments",
"products.exports",
"products.product_analytics",
]
layer = "modules"
[[modules]]
path = "products.streamlit_apps"
depends_on = [
"insights",
"products.tasks",
]
layer = "modules"
[[modules]]
path = "products.notifications"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.platform_features"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.insights_ai"
depends_on = [
"ee",
"insights",
"products.error_tracking",
"products.event_definitions",
"products.ai_observability",
"products.logs",
"products.tasks",
]
layer = "modules"
[[modules]]
path = "products.product_analytics"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.actions",
"products.alerts",
"products.dashboards",
"products.event_definitions",
"products.annotations",
"products.warehouse_sources",
]
layer = "modules"
[[modules]]
path = "products.product_tours"
depends_on = [
"insights",
"products.approvals",
"products.feature_flags",
"products.surveys",
]
layer = "modules"
[[modules]]
path = "products.reminders"
depends_on = [
"insights",
"products.dashboards",
"products.error_tracking",
"products.experiments",
"products.feature_flags",
"products.notebooks",
"products.notifications",
"products.product_analytics",
"products.surveys",
]
layer = "modules"
[[modules]]
path = "products.replay"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.replay_vision"
depends_on = [
"ee",
"insights",
"products.cdp",
"products.cohorts",
"products.exports",
"products.signals",
"products.tasks",
]
layer = "modules"
[[modules]]
path = "products.revenue_analytics"
depends_on = [
"ee",
"insights", "products.warehouse_sources", "products.data_modeling", "products.data_tools",
]
layer = "modules"
[[modules]]
path = "products.review"
depends_on = [
"ee",
"insights",
"products.engineering_analytics",
"products.signals",
"products.skills",
# Facade-only (enforced by stamp's [[interfaces]] block): the inbox trigger queues
# hosted Stamp reviews and registers the toggle resolver hook.
"products.stamp",
"products.tasks",
]
layer = "modules"
[[modules]]
path = "products.signals"
depends_on = [
"ee",
"products.cohorts",
"insights",
"products.actions",
"products.alerts",
"products.cdp",
"products.conversations",
"products.dashboards",
"products.data_warehouse",
"products.error_tracking",
"products.experiments",
"products.feature_flags",
"products.notebooks",
"products.product_analytics",
"products.skills",
"products.surveys",
"products.tasks",
"products.warehouse_sources",
"products.workflows", "products.business_knowledge",
]
layer = "modules"
[[modules]]
# Skills imports ai_observability's shared markdown_outline + API metrics helpers —
# temporary coupling from the standalone-product extraction, slated for cleanup.
path = "products.skills"
depends_on = [
"ee",
"insights",
"products.ai_observability",
]
layer = "modules"
[[modules]]
path = "products.slack_app"
depends_on = [
"insights",
"products.alerts",
"products.conversations",
"products.dashboards",
"products.product_analytics",
"products.signals",
"products.tasks",
]
layer = "modules"
[[modules]]
path = "products.surveys"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.actions",
"products.feature_flags",
"products.product_analytics",
"products.product_tours",
]
layer = "modules"
[[modules]]
path = "products.customer_analytics"
depends_on = [
"ee",
"insights",
"products.cdp",
"products.conversations",
"products.data_warehouse",
"products.notebooks",
"products.notifications",
"products.product_analytics",
"products.warehouse_sources",
"products.workflows",
]
layer = "modules"
[[modules]]
path = "products.managed_warehouse"
depends_on = [
"ee",
"insights",
"products.data_warehouse",
"products.data_modeling",
"products.warehouse_sources",
]
layer = "modules"
[[modules]]
path = "products.marketing_analytics"
depends_on = [
"ee",
"insights",
"products.access_control",
"products.actions",
"products.analytics_platform", "products.warehouse_sources",
"products.feature_flags",
]
layer = "modules"
[[modules]]
path = "products.tasks"
depends_on = [
"ee",
"insights",
"products.error_tracking",
"products.event_definitions",
"products.exports",
"products.feature_flags",
"products.ai_observability",
"products.mcp_store",
"products.notifications",
"products.insights_ai",
"products.signals",
"products.slack_app",
]
layer = "modules"
[[modules]]
path = "products.canvas"
depends_on = [
"insights",
# Sandbox provisioning (via the tasks facade) and the Channel FK canvases file into.
"products.tasks",
]
layer = "modules"
# Canvas's public surface: routes + presentation for the API layer, tasks for
# the Celery registrations insights/tasks/scheduled.py imports.
[[interfaces]]
expose = [
"backend\\.routes.*",
]
from = [
"products.canvas",
]
[[interfaces]]
expose = [
"backend\\.artifacts.*",
"backend\\.tasks.*",
]
from = [
"products.canvas",
]
[[modules]]
path = "products.tracing"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.user_interviews"
depends_on = [
"ee",
"insights",
"products.ai_observability",
]
layer = "modules"
[[modules]]
path = "products.visual_review"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.warehouse_sources_queue"
depends_on = [
"insights",
]
layer = "modules"
[[modules]]
path = "products.web_analytics"
depends_on = [
"products.access_control",
"products.cohorts",
"ee",
"insights",
"products.actions",
"products.analytics_platform",
"products.notifications",
"products.replay_vision",
]
layer = "modules"
[[modules]]
path = "products.workflows"
depends_on = [
"products.cohorts",
"ee",
"insights",
"products.actions",
"products.cdp",
"products.feature_flags",
"products.messaging",
"products.notifications",
]
layer = "modules"
# Facade + views: the canonical public surface for all isolated products.
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
"backend\\.routes.*",
]
from = [
"products\\.(customer_analytics|data_modeling|data_warehouse|demo|endpoints|error_tracking|experiments|managed_warehouse|mcp_analytics|mcp_store|metrics|notebooks|notifications|streamlit_apps|tasks|tracing|user_interviews|visual_review|warehouse_sources)",
]
# TODO: Experiments-specific temporary interface
# Remove this block once all ViewSets are migrated to products/experiments/backend/presentation/views.py
[[interfaces]]
expose = [
"backend\\.presentation\\.experiments.*",
"backend\\.presentation\\.saved_metrics.*",
]
from = [
"products.experiments",
]
# Experiments is the first isolated product to register a Temporal workflow, so the canonical interface
# doesn't cover the registration surface yet. Narrowly expose the symbols core imports (worker registration,
# schedule registration, and the worker interceptor) rather than widening every isolated product's surface.
[[interfaces]]
expose = [
"backend\\.temporal\\.ACTIVITIES",
"backend\\.temporal\\.EXPERIMENT_CANARY_ACTIVITIES",
"backend\\.temporal\\.EXPERIMENT_CANARY_WORKFLOWS",
"backend\\.temporal\\.WORKFLOWS",
"backend\\.temporal\\.recalculation_metrics.*",
"backend\\.temporal\\.schedule\\.create_experiment_precompute_canary_schedule",
]
from = [
"products.experiments",
]
# user_interviews exposes Vapi webhook handlers that are routed directly from insights/urls.py.
[[interfaces]]
expose = [
"backend\\.presentation\\.webhooks.*",
]
from = [
"products.user_interviews",
]
# streamlit_apps exposes the InsightsQL bridge view, routed directly from insights/urls.py.
[[interfaces]]
expose = [
"backend\\.presentation\\.bridge_views.*",
]
from = [
"products.streamlit_apps",
]
# Legacy leaks — core (insights/ee) imports these internals directly.
# Each block below should shrink as imports migrate to the facade.
# These products have had backend:contract-check removed from package.json
# so CI treats them as non-isolated until the leaks are cleaned up.
[[interfaces]]
expose = [
"backend\\.analysis_health.*",
"backend\\.experiment_saved_metric_service.*",
"backend\\.experiment_service.*",
"backend\\.insightsql_queries.*",
"backend\\.llm_metric_templates.*",
"backend\\.max_tools.*",
"backend\\.metric_utils.*",
"backend\\.models.*",
"stats\\..*",
]
from = [
"products.experiments",
]
[[interfaces]]
expose = [
"backend\\.admin.*",
"backend\\.models.*",
"backend\\.oauth.*",
]
from = [
"products.mcp_store",
]
# isolation:permanent-interface
# warehouse_sources' InsightsQL direct-SQL adapters and its system-table definitions depend on a
# handful of source internals + models that the facade re-exports lazily — facade.source_management
# is a thin PEP 562 re-export, so a change to the underlying source flows through to core. That
# coupling can't be sealed by watching backend.facade alone, so these modules are declared
# permanent and turbo.json keeps them in the contract-check inputs — any change to them still
# re-runs the Django suite (IsolationChainCheck enforces that). The vendor set is exactly the
# sources core reaches through the facade, guarded by test_ci_core_coupled_sources.py. All other
# core coupling goes through backend.facade.
[[interfaces]]
expose = [
"backend\\.models.*",
"backend\\.temporal\\.data_imports\\.sources\\.common.*",
"backend\\.temporal\\.data_imports\\.sources\\.generated_configs.*",
"backend\\.temporal\\.data_imports\\.sources\\.google_search_console.*",
"backend\\.temporal\\.data_imports\\.sources\\.mysql.*",
"backend\\.temporal\\.data_imports\\.sources\\.postgres.*",
"backend\\.temporal\\.data_imports\\.sources\\.redshift.*",
"backend\\.temporal\\.data_imports\\.sources\\.salesforce.*",
"backend\\.temporal\\.data_imports\\.sources\\.snowflake.*",
"backend\\.temporal\\.data_imports\\.sources\\.stripe.*",
]
from = [
"products.warehouse_sources",
]
# legal_documents has a non-standard public surface — insights/urls registers its pandadoc
# webhook (presentation.webhook), not the canonical presentation.views — so it gets a dedicated
# block rather than joining the canonical alternation above.
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation.*",
"backend\\.routes.*",
]
from = [
"products.legal_documents",
]
# isolation:permanent-interface
# error_tracking exposes its Datastore DDL (sql / embedding / indexed_embedding) to core's
# Datastore schema registry, conftest, the embedding worker, the insightsql document_embeddings
# system table, and frozen Datastore migrations. That coupling is outside the import-reroute
# path — frozen migrations hardcode these import paths and the schema registry owns table DDL —
# so it can never route through the facade. The marker above declares it permanent rather than a
# legacy leak, so it does not hold the external seal open. turbo.json keeps these three modules
# in the contract-check inputs so any change to them still re-runs the Django suite
# (IsolationChainCheck enforces that). All other core coupling now goes through backend.facade.
[[interfaces]]
expose = [
"backend\\.embedding.*",
"backend\\.indexed_embedding.*",
"backend\\.sql.*",
]
from = [
"products.error_tracking",
]
[[interfaces]]
expose = [
"backend\\.logic.*",
]
from = [
"products.tracing",
]
# TODO: legacy leaks — insights/temporal/mcp_analytics/* and the dashboard
# integration import models / dashboard_templates / intent_clustering directly.
# Move those into the product (and through the facade) so this interface can
# shrink back to the isolated default.
[[interfaces]]
expose = [
"backend\\.dashboard_templates.*",
"backend\\.intent_clustering.*",
"backend\\.models.*",
]
from = [
"products.mcp_analytics",
]
[[modules]]
path = "products.legal_documents"
depends_on = [
"ee",
"insights",
]
layer = "modules"
[[modules]]
path = "products.access_control"
depends_on = [
"insights",
"ee",
]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
"backend\\.routes.*",
]
from = [
"products.access_control",
]
# Legacy leaks — core (insights/ee) still imports these internals directly.
[[interfaces]]
expose = [
"backend\\.models.*",
"backend\\.property_access_control.*",
]
from = [
"products.access_control",
]
# Legacy leaks — core (insights/ee), customer_analytics, reminders and signals still
# import the Notebook ORM directly: file-system / search / reminders registries dispatch
# on the model class, middleware returns a raw queryset, the read_data and notebook-context
# Max tools need the instance for access-control checks, sharing re-fetches it for the
# shared-export serializer, and customer_analytics owns a CRUD-over-Notebook surface that
# moves in its own presentation wave. Shrinks as those migrate behind the facade; keeps
# backend:contract-check off until empty.
[[interfaces]]
expose = [
"backend\\.models.*",
]
from = [
"products.notebooks",
]
[[modules]]
path = "products.business_knowledge"
depends_on = ["insights", "ee"]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.api.*",
"backend\\.logic.*",
"backend\\.constants.*",
"backend\\.models.*",
"backend\\.temporal.*",
]
from = [
"products.business_knowledge",
]
[[interfaces]]
expose = [
"backend\\.routes.*",
]
from = [
"products.business_knowledge",
]
[[modules]]
path = "products.wizard"
depends_on = ["insights", "products.event_definitions"]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.logic\\.placeholder.*",
"backend\\.models.*",
"backend\\.property_type.*",
]
from = [
"products.event_definitions",
]
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
"backend\\.routes.*",
]
from = [
"products.wizard",
]
[[modules]]
path = "products.engineering_analytics"
depends_on = ["insights", "products.data_modeling", "products.warehouse_sources", "products.signals"]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
"backend\\.routes.*",
]
from = [
"products.engineering_analytics",
]
[[modules]]
path = "products.exports"
depends_on = ["insights", "products.actions", "products.dashboards", "ee", "products.annotations", "products.insights_ai", "products.product_analytics"]
layer = "modules"
[[modules]]
path = "products.annotations"
depends_on = ["insights", "products.product_analytics", "products.dashboards"]
layer = "modules"
[[modules]]
path = "products.field_notes"
depends_on = ["insights"]
layer = "modules"
[[modules]]
path = "products.stamp"
depends_on = ["insights", "products.tasks"]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
]
from = [
"products.stamp",
]
[[modules]]
path = "products.data_catalog"
depends_on = [
"insights",
"products.data_tools",
"products.product_analytics",
"products.warehouse_sources",
"products.data_modeling",
]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
]
from = [
"products.data_catalog",
]
[[modules]]
path = "products.apm"
depends_on = ["insights"]
layer = "modules"
[[interfaces]]
expose = [
"backend\\.facade.*",
"backend\\.presentation\\.views.*",
]
from = [
"products.apm",
]