2026-08-18-data-factory-kestra-n8n-navigation-separation.md 9.5 KB

Data Factory Kestra / n8n Navigation Separation Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Give governed Kestra production deployment and legacy n8n management independent Data Factory navigation and page lifecycles.

Architecture: Move the Kestra deployment component out of the n8n workflow directory and expose it through a dedicated internal route. Keep the two n8n surfaces explicitly marked as legacy, preserve their current adapters, and protect the separation with source-level navigation contracts plus a production frontend build and Docker smoke test.

Tech Stack: Vue 2, Vue Router, Vuetify, Python pytest contract tests, Docker Compose.


File Structure

  • Create tests/test_data_factory_orchestration_navigation_contract.py: owns the engine-separation navigation contract.
  • Modify tests/test_data_rule_frontend_contract.py: points the existing governed deployment assertions at the new Kestra page.
  • Modify frontend/src/router/routes.js: defines independent Kestra and legacy n8n menu entries.
  • Create frontend/src/views/dataFactory/productionLineDeployment/index.vue: dedicated Kestra production deployment page, moved from the n8n directory.
  • Modify frontend/src/views/dataFactory/workflow/index.vue: retains only n8n workflow list, executions, and health.
  • Remove frontend/src/views/dataFactory/workflow/ProductionLineDeployment.vue: eliminates the physical page coupling.

Task 1: Add the failing navigation-separation contract

Files:

  • Create: tests/test_data_factory_orchestration_navigation_contract.py
  • Test: tests/test_data_factory_orchestration_navigation_contract.py

  • [ ] Step 1: Write the failing contract

from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
ROUTES = ROOT / "frontend/src/router/routes.js"
N8N_PAGE = ROOT / "frontend/src/views/dataFactory/workflow/index.vue"
KESTRA_PAGE = ROOT / "frontend/src/views/dataFactory/productionLineDeployment/index.vue"


def test_data_factory_exposes_independent_kestra_and_legacy_n8n_navigation():
    routes = ROUTES.read_text(encoding="utf-8")
    assert "数据生产线投产" in routes
    assert "'/dataFactory/production-line-deployment'" in routes
    assert "dataFactory/productionLineDeployment" in routes
    assert "n8n 生产线管理(待下线)" in routes
    assert "n8n 工作流管理(待下线)" in routes
    assert routes.index("数据生产线投产") < routes.index("n8n 生产线管理(待下线)")


def test_kestra_page_is_not_owned_by_the_n8n_workflow_page():
    legacy = N8N_PAGE.read_text(encoding="utf-8")
    kestra = KESTRA_PAGE.read_text(encoding="utf-8")
    assert "ProductionLineDeployment" not in legacy
    assert "数据生产线投产" not in legacy
    assert "工作流列表" in legacy
    assert "执行记录" in legacy
    assert "健康检查" in legacy
    assert "DATA FACTORY · GOVERNED RELEASE" in kestra
    assert "Kestra revision" in kestra
  • Step 2: Run the contract and verify RED

Run: PYTHONPATH=. .venv/bin/pytest -q tests/test_data_factory_orchestration_navigation_contract.py

Expected: FAIL because the dedicated Kestra route/page does not exist and the n8n page still imports ProductionLineDeployment.

  • Step 3: Commit the RED contract
git add tests/test_data_factory_orchestration_navigation_contract.py
git commit -m "test: define Kestra and n8n navigation boundary"

Task 2: Create the dedicated Kestra page and remove the n8n tab coupling

Files:

  • Create: frontend/src/views/dataFactory/productionLineDeployment/index.vue
  • Remove: frontend/src/views/dataFactory/workflow/ProductionLineDeployment.vue
  • Modify: frontend/src/views/dataFactory/workflow/index.vue
  • Modify: tests/test_data_rule_frontend_contract.py

  • [ ] Step 1: Move the governed deployment component

Move frontend/src/views/dataFactory/workflow/ProductionLineDeployment.vue byte-for-byte to frontend/src/views/dataFactory/productionLineDeployment/index.vue. Its imports use the @/api/dataRules alias, so the move does not change runtime dependencies.

  • Step 2: Remove the Kestra tab from the legacy n8n page

Make frontend/src/views/dataFactory/workflow/index.vue contain only:

<v-tabs v-model="tab" @change="handleTabChange">
  <v-tab>工作流列表</v-tab>
  <v-tab>执行记录</v-tab>
  <v-tab>健康检查</v-tab>
</v-tabs>

Remove the ProductionLineDeployment import, component registration, and tab item. Keep ExecutionRecord :tab="tab" aligned with the new three-tab index.

  • Step 3: Point the existing governed frontend contract at the new page

Change the constants in tests/test_data_rule_frontend_contract.py to:

FACTORY = Path(
    "frontend/src/views/dataFactory/productionLineDeployment/index.vue"
)
FACTORY_INDEX = FACTORY

The existing assertions continue to prove deployment, canary, activation, rollback, evidence, and readiness behavior.

  • Step 4: Run focused tests

Run:

PYTHONPATH=. .venv/bin/pytest -q \
  tests/test_data_factory_orchestration_navigation_contract.py \
  tests/test_data_rule_frontend_contract.py

Expected: navigation test still fails only because the new router entry is absent; existing governed deployment assertions pass at the new location.

Task 3: Add independent router entries and legacy labels

Files:

  • Modify: frontend/src/router/routes.js
  • Test: tests/test_data_factory_orchestration_navigation_contract.py

  • [ ] Step 1: Insert the Kestra entry before the legacy entries

Add a Data Factory child with this contract:

{
  meun: '',
  code: '',
  hidden: 0,
  rootId: 972,
  icon: '',
  remark: '',
  type: 1,
  title: '数据生产线投产',
  local: '',
  path: '/dataFactory/production-line-deployment',
  urls: '',
  children: [],
  enName: 'Kestra Production Deployment',
  id: 979,
  redirect: '',
  level: 2,
  openPath: '',
  active: '',
  label: '数据生产线投产',
  sort: 5,
  parentId: 972,
  effectiveStatus: true,
  parentName: 'dataFactory',
  component: 'dataFactory/productionLineDeployment',
  meta: {
    keepAlive: false,
    allowClick: false,
    roles: [],
    enName: 'Kestra Production Deployment',
    icon: '',
    editModules: false,
    title: '数据生产线投产',
    fullScreen: false,
    target: false,
    effectiveStatus: true
  },
  name: 'productionLineDeployment',
  style: '',
  alwaysShow: 0,
  metastr: '{"keepAlive":false,"allowClick":false,"enName":"Kestra Production Deployment","editModules":false,"title":"数据生产线投产","fullScreen":false,"target":false}',
  open: null
}
  • Step 2: Rename the two n8n entries without changing behavior

Update the current external entry label/title to n8n 生产线管理(待下线) while retaining process.env.VUE_APP_N8N_URL and target: true.

Update the current internal workflow entry label/title to n8n 工作流管理(待下线) while retaining /dataFactory/workflow, component dataFactory/workflow, and target: false.

  • Step 3: Run RED-to-GREEN contract tests

Run:

PYTHONPATH=. .venv/bin/pytest -q \
  tests/test_data_factory_orchestration_navigation_contract.py \
  tests/test_data_rule_frontend_contract.py \
  tests/test_cleanup_contract.py \
  tests/test_architecture_artifacts.py

Expected: PASS.

  • Step 4: Commit the implementation
git add \
  frontend/src/router/routes.js \
  frontend/src/views/dataFactory/workflow/index.vue \
  frontend/src/views/dataFactory/productionLineDeployment/index.vue \
  frontend/src/views/dataFactory/workflow/ProductionLineDeployment.vue \
  tests/test_data_rule_frontend_contract.py
git commit -m "feat: separate Kestra and legacy n8n navigation"

Task 4: Build, deploy, and verify the local UAT frontend

Files:

  • Verify: frontend/
  • Verify: deploy/docker/docker-compose.yml

  • [ ] Step 1: Build the production frontend

Run: npm --prefix frontend run build

Expected: exit 0 with a generated production bundle and no route-resolution error.

  • Step 2: Rebuild and restart only the frontend service

Run: docker compose -f deploy/docker/docker-compose.yml up -d --build frontend

Expected: frontend and its dependencies remain healthy; backend, Kestra, and n8n state are preserved.

  • Step 3: Verify service health and deep links

Run:

docker compose -f deploy/docker/docker-compose.yml ps
curl -fsS http://localhost:18183/dataFactory/production-line-deployment >/dev/null
curl -fsS http://localhost:18183/dataFactory/workflow >/dev/null

Expected: frontend is healthy and both internal routes return the SPA document.

  • Step 4: Browser acceptance

Verify in the local UAT UI:

  1. 数据工厂 > 数据生产线投产 opens the governed Kestra page.
  2. 数据工厂 > n8n 生产线管理(待下线) opens the current n8n URL.
  3. 数据工厂 > n8n 工作流管理(待下线) shows only three n8n tabs.
  4. Refreshing either internal deep link does not produce a 404.
  • Step 5: Run final source checks and commit any generated contract update

Run:

git diff --check
PYTHONPATH=. .venv/bin/pytest -q \
  tests/test_data_factory_orchestration_navigation_contract.py \
  tests/test_data_rule_frontend_contract.py \
  tests/test_cleanup_contract.py \
  tests/test_architecture_artifacts.py

Expected: all tests pass and git diff --check emits no output.