revoluzen-flow 1.0.1.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (942) hide show
  1. revoluzen_flow/CHANGELOG.md +724 -0
  2. revoluzen_flow/README.md +648 -0
  3. revoluzen_flow/__init__.py +17 -0
  4. revoluzen_flow/__main__.py +25 -0
  5. revoluzen_flow/ai/__init__.py +0 -0
  6. revoluzen_flow/ai/agent.py +1325 -0
  7. revoluzen_flow/ai/ai_metrics.py +185 -0
  8. revoluzen_flow/ai/anthropic_client.py +120 -0
  9. revoluzen_flow/ai/atlas/__init__.py +71 -0
  10. revoluzen_flow/ai/atlas/schema.py +275 -0
  11. revoluzen_flow/ai/atlas/topics_autogen.py +327 -0
  12. revoluzen_flow/ai/atlas/topics_handwritten.py +1165 -0
  13. revoluzen_flow/ai/budget.py +147 -0
  14. revoluzen_flow/ai/cache.py +153 -0
  15. revoluzen_flow/ai/clarify.py +317 -0
  16. revoluzen_flow/ai/clarify_draft.py +1706 -0
  17. revoluzen_flow/ai/clarify_to_template.py +396 -0
  18. revoluzen_flow/ai/column_refs.py +149 -0
  19. revoluzen_flow/ai/context.py +227 -0
  20. revoluzen_flow/ai/cost_rates.py +333 -0
  21. revoluzen_flow/ai/dialogue_state.py +454 -0
  22. revoluzen_flow/ai/direct_actions.py +333 -0
  23. revoluzen_flow/ai/draft_checks.py +175 -0
  24. revoluzen_flow/ai/draft_choices.py +785 -0
  25. revoluzen_flow/ai/draft_diff.py +219 -0
  26. revoluzen_flow/ai/draft_guess.py +289 -0
  27. revoluzen_flow/ai/dry_run_promoter.py +152 -0
  28. revoluzen_flow/ai/embedded.py +2053 -0
  29. revoluzen_flow/ai/fast_router.py +3883 -0
  30. revoluzen_flow/ai/foundation.py +99 -0
  31. revoluzen_flow/ai/governance.py +136 -0
  32. revoluzen_flow/ai/handles.py +124 -0
  33. revoluzen_flow/ai/hybrid.py +342 -0
  34. revoluzen_flow/ai/idempotency.py +119 -0
  35. revoluzen_flow/ai/interactive_cards.py +235 -0
  36. revoluzen_flow/ai/json_repair.py +280 -0
  37. revoluzen_flow/ai/multi_step.py +50 -0
  38. revoluzen_flow/ai/normalize.py +151 -0
  39. revoluzen_flow/ai/notification_summary.py +230 -0
  40. revoluzen_flow/ai/ollama_client.py +348 -0
  41. revoluzen_flow/ai/openai_client.py +281 -0
  42. revoluzen_flow/ai/openai_compatible_client.py +101 -0
  43. revoluzen_flow/ai/openrouter_client.py +230 -0
  44. revoluzen_flow/ai/product_knowledge.py +410 -0
  45. revoluzen_flow/ai/prompt_signing.py +116 -0
  46. revoluzen_flow/ai/rag/__init__.py +22 -0
  47. revoluzen_flow/ai/rag/embedder.py +73 -0
  48. revoluzen_flow/ai/rag/indexer.py +287 -0
  49. revoluzen_flow/ai/rag/retrieve.py +94 -0
  50. revoluzen_flow/ai/rag/store.py +242 -0
  51. revoluzen_flow/ai/rate_limit.py +341 -0
  52. revoluzen_flow/ai/rbac.py +153 -0
  53. revoluzen_flow/ai/roles.py +190 -0
  54. revoluzen_flow/ai/sanitize.py +191 -0
  55. revoluzen_flow/ai/schema_infer.py +341 -0
  56. revoluzen_flow/ai/semantic_cache.py +257 -0
  57. revoluzen_flow/ai/session_context.py +579 -0
  58. revoluzen_flow/ai/single_shot.py +206 -0
  59. revoluzen_flow/ai/sql_templates.py +565 -0
  60. revoluzen_flow/ai/step_params.py +35 -0
  61. revoluzen_flow/ai/tls.py +18 -0
  62. revoluzen_flow/ai/tool_only_mode.py +58 -0
  63. revoluzen_flow/ai/tool_selector.py +380 -0
  64. revoluzen_flow/ai/tools/__init__.py +252 -0
  65. revoluzen_flow/ai/tools/_edit_guards.py +534 -0
  66. revoluzen_flow/ai/tools/apply_pipeline_draft.py +165 -0
  67. revoluzen_flow/ai/tools/base.py +124 -0
  68. revoluzen_flow/ai/tools/compose_report.py +89 -0
  69. revoluzen_flow/ai/tools/draft_alert_rule.py +121 -0
  70. revoluzen_flow/ai/tools/draft_connector_from_openapi.py +198 -0
  71. revoluzen_flow/ai/tools/draft_connector_from_samples.py +146 -0
  72. revoluzen_flow/ai/tools/draft_pipeline_from_intent.py +220 -0
  73. revoluzen_flow/ai/tools/explain_step.py +252 -0
  74. revoluzen_flow/ai/tools/get_incidents.py +96 -0
  75. revoluzen_flow/ai/tools/get_installation_health.py +212 -0
  76. revoluzen_flow/ai/tools/get_next_scheduled.py +108 -0
  77. revoluzen_flow/ai/tools/get_pipeline_spec.py +138 -0
  78. revoluzen_flow/ai/tools/get_running_executions.py +88 -0
  79. revoluzen_flow/ai/tools/get_security_posture.py +152 -0
  80. revoluzen_flow/ai/tools/get_user_role.py +71 -0
  81. revoluzen_flow/ai/tools/inspect_connections.py +85 -0
  82. revoluzen_flow/ai/tools/inspect_step_columns.py +209 -0
  83. revoluzen_flow/ai/tools/list_alerts.py +53 -0
  84. revoluzen_flow/ai/tools/list_catalog.py +165 -0
  85. revoluzen_flow/ai/tools/list_executions.py +178 -0
  86. revoluzen_flow/ai/tools/list_pipelines.py +96 -0
  87. revoluzen_flow/ai/tools/list_projects.py +49 -0
  88. revoluzen_flow/ai/tools/list_quality_rule_sets.py +71 -0
  89. revoluzen_flow/ai/tools/list_schedules.py +77 -0
  90. revoluzen_flow/ai/tools/list_steward_findings.py +204 -0
  91. revoluzen_flow/ai/tools/list_storage.py +236 -0
  92. revoluzen_flow/ai/tools/list_templates.py +184 -0
  93. revoluzen_flow/ai/tools/lookup_business_terms.py +70 -0
  94. revoluzen_flow/ai/tools/lookup_help_topic.py +159 -0
  95. revoluzen_flow/ai/tools/modify_pipeline_step.py +462 -0
  96. revoluzen_flow/ai/tools/query_metrics.py +77 -0
  97. revoluzen_flow/ai/tools/recall_history.py +116 -0
  98. revoluzen_flow/ai/tools/registry.py +86 -0
  99. revoluzen_flow/ai/tools/suggest_join_keys.py +130 -0
  100. revoluzen_flow/ai/tools/summarize_pipeline.py +164 -0
  101. revoluzen_flow/ai/tools/test_connection.py +119 -0
  102. revoluzen_flow/ai/tools/test_pipeline_draft.py +313 -0
  103. revoluzen_flow/ai/tools/validate_pipeline.py +311 -0
  104. revoluzen_flow/ai/tools/web_fetch.py +108 -0
  105. revoluzen_flow/ai/tools/web_search.py +83 -0
  106. revoluzen_flow/ai/tools/workspace_overview.py +63 -0
  107. revoluzen_flow/ai/trace_store.py +483 -0
  108. revoluzen_flow/ai/usage_sources.py +175 -0
  109. revoluzen_flow/ai/wallet.py +287 -0
  110. revoluzen_flow/ai/web/__init__.py +108 -0
  111. revoluzen_flow/ai/web/fetch.py +110 -0
  112. revoluzen_flow/ai/web/search.py +235 -0
  113. revoluzen_flow/ai_config/__init__.py +5 -0
  114. revoluzen_flow/ai_config/store.py +447 -0
  115. revoluzen_flow/alerts/__init__.py +4 -0
  116. revoluzen_flow/alerts/models.py +125 -0
  117. revoluzen_flow/alerts/notifier.py +1442 -0
  118. revoluzen_flow/alerts/store.py +443 -0
  119. revoluzen_flow/api/__init__.py +149 -0
  120. revoluzen_flow/api/activity.py +354 -0
  121. revoluzen_flow/api/addons.py +99 -0
  122. revoluzen_flow/api/agent.py +2421 -0
  123. revoluzen_flow/api/agent_action.py +297 -0
  124. revoluzen_flow/api/ai.py +2467 -0
  125. revoluzen_flow/api/ai_config.py +662 -0
  126. revoluzen_flow/api/ai_cost_rates.py +83 -0
  127. revoluzen_flow/api/ai_roles.py +65 -0
  128. revoluzen_flow/api/ai_web.py +122 -0
  129. revoluzen_flow/api/alerts.py +292 -0
  130. revoluzen_flow/api/api_explorer.py +435 -0
  131. revoluzen_flow/api/app_meta.py +106 -0
  132. revoluzen_flow/api/auth.py +2030 -0
  133. revoluzen_flow/api/auth_health.py +56 -0
  134. revoluzen_flow/api/backfills.py +481 -0
  135. revoluzen_flow/api/backup.py +361 -0
  136. revoluzen_flow/api/catalog.py +370 -0
  137. revoluzen_flow/api/cert_matrix.py +954 -0
  138. revoluzen_flow/api/collaboration.py +186 -0
  139. revoluzen_flow/api/connections.py +1124 -0
  140. revoluzen_flow/api/connector_authoring.py +342 -0
  141. revoluzen_flow/api/connector_drafts.py +108 -0
  142. revoluzen_flow/api/contracts.py +357 -0
  143. revoluzen_flow/api/credentials.py +512 -0
  144. revoluzen_flow/api/dashboard.py +746 -0
  145. revoluzen_flow/api/deployments.py +332 -0
  146. revoluzen_flow/api/errors.py +200 -0
  147. revoluzen_flow/api/execution.py +1938 -0
  148. revoluzen_flow/api/execution_contracts.py +284 -0
  149. revoluzen_flow/api/execution_manager.py +200 -0
  150. revoluzen_flow/api/exports.py +259 -0
  151. revoluzen_flow/api/expressions.py +104 -0
  152. revoluzen_flow/api/extraction.py +207 -0
  153. revoluzen_flow/api/folders.py +405 -0
  154. revoluzen_flow/api/gateway.py +766 -0
  155. revoluzen_flow/api/git_copy.py +132 -0
  156. revoluzen_flow/api/glossary.py +106 -0
  157. revoluzen_flow/api/health_memory.py +338 -0
  158. revoluzen_flow/api/incidents.py +141 -0
  159. revoluzen_flow/api/intelligence.py +681 -0
  160. revoluzen_flow/api/legacy_files.py +104 -0
  161. revoluzen_flow/api/lineage.py +241 -0
  162. revoluzen_flow/api/local_hardening.py +437 -0
  163. revoluzen_flow/api/logs.py +184 -0
  164. revoluzen_flow/api/marketplace.py +166 -0
  165. revoluzen_flow/api/mcp.py +287 -0
  166. revoluzen_flow/api/metrics.py +443 -0
  167. revoluzen_flow/api/monitor.py +707 -0
  168. revoluzen_flow/api/notifications.py +384 -0
  169. revoluzen_flow/api/ollama.py +390 -0
  170. revoluzen_flow/api/pipeline_health.py +102 -0
  171. revoluzen_flow/api/planner.py +865 -0
  172. revoluzen_flow/api/plugins.py +92 -0
  173. revoluzen_flow/api/pool.py +748 -0
  174. revoluzen_flow/api/pool_allocation.py +212 -0
  175. revoluzen_flow/api/pre_publish.py +294 -0
  176. revoluzen_flow/api/product_knowledge.py +155 -0
  177. revoluzen_flow/api/projects.py +926 -0
  178. revoluzen_flow/api/publish_policy.py +129 -0
  179. revoluzen_flow/api/quality_rule_sets.py +149 -0
  180. revoluzen_flow/api/recipes.py +307 -0
  181. revoluzen_flow/api/report_builder.py +482 -0
  182. revoluzen_flow/api/reports.py +980 -0
  183. revoluzen_flow/api/router_audit.py +213 -0
  184. revoluzen_flow/api/router_coverage.py +314 -0
  185. revoluzen_flow/api/router_telemetry.py +258 -0
  186. revoluzen_flow/api/router_tests.py +428 -0
  187. revoluzen_flow/api/schedules.py +472 -0
  188. revoluzen_flow/api/schema_history.py +310 -0
  189. revoluzen_flow/api/security_headers.py +147 -0
  190. revoluzen_flow/api/steward.py +1691 -0
  191. revoluzen_flow/api/storage.py +2605 -0
  192. revoluzen_flow/api/sync_state.py +91 -0
  193. revoluzen_flow/api/system.py +207 -0
  194. revoluzen_flow/api/templates.py +358 -0
  195. revoluzen_flow/api/trust.py +421 -0
  196. revoluzen_flow/api/trust_checks.py +286 -0
  197. revoluzen_flow/api/types_meta.py +104 -0
  198. revoluzen_flow/api/uploads.py +256 -0
  199. revoluzen_flow/api/variables.py +150 -0
  200. revoluzen_flow/api/websocket.py +635 -0
  201. revoluzen_flow/api/workflows.py +4285 -0
  202. revoluzen_flow/api/workspace_settings.py +134 -0
  203. revoluzen_flow/api/workspaces.py +394 -0
  204. revoluzen_flow/app_meta.py +50 -0
  205. revoluzen_flow/audit.py +114 -0
  206. revoluzen_flow/auth/__init__.py +4 -0
  207. revoluzen_flow/auth/deps.py +340 -0
  208. revoluzen_flow/auth/models.py +247 -0
  209. revoluzen_flow/auth/password_policy.py +269 -0
  210. revoluzen_flow/auth/store.py +370 -0
  211. revoluzen_flow/backfills/__init__.py +45 -0
  212. revoluzen_flow/backfills/idempotency.py +128 -0
  213. revoluzen_flow/backfills/models.py +138 -0
  214. revoluzen_flow/backfills/orchestrator.py +368 -0
  215. revoluzen_flow/backfills/preflight.py +162 -0
  216. revoluzen_flow/backfills/store.py +269 -0
  217. revoluzen_flow/backfills/windows.py +152 -0
  218. revoluzen_flow/cli/__init__.py +1571 -0
  219. revoluzen_flow/cli/install_service.py +565 -0
  220. revoluzen_flow/cli/launcher.py +400 -0
  221. revoluzen_flow/cli/runtime_state.py +315 -0
  222. revoluzen_flow/collaboration/__init__.py +193 -0
  223. revoluzen_flow/common/__init__.py +1 -0
  224. revoluzen_flow/common/client_ip.py +179 -0
  225. revoluzen_flow/common/duckdb_compat.py +56 -0
  226. revoluzen_flow/common/http_reply.py +258 -0
  227. revoluzen_flow/common/safe_paths.py +103 -0
  228. revoluzen_flow/common/safe_xml.py +573 -0
  229. revoluzen_flow/common/unique_name.py +65 -0
  230. revoluzen_flow/compile/__init__.py +5 -0
  231. revoluzen_flow/compile/sql_preview.py +675 -0
  232. revoluzen_flow/connections/__init__.py +4 -0
  233. revoluzen_flow/connections/addon_installer.py +317 -0
  234. revoluzen_flow/connections/addons.py +67 -0
  235. revoluzen_flow/connections/capability_levels.py +310 -0
  236. revoluzen_flow/connections/catalog.py +1250 -0
  237. revoluzen_flow/connections/catalog_extensions.py +1804 -0
  238. revoluzen_flow/connections/cli.py +250 -0
  239. revoluzen_flow/connections/credentials.py +136 -0
  240. revoluzen_flow/connections/fanout_runner.py +325 -0
  241. revoluzen_flow/connections/file_share.py +563 -0
  242. revoluzen_flow/connections/http_auth.py +181 -0
  243. revoluzen_flow/connections/inline_secrets.py +253 -0
  244. revoluzen_flow/connections/kafka_settings.py +458 -0
  245. revoluzen_flow/connections/models.py +313 -0
  246. revoluzen_flow/connections/mssql_odbc.py +79 -0
  247. revoluzen_flow/connections/oauth_flows.py +251 -0
  248. revoluzen_flow/connections/oauth_health.py +156 -0
  249. revoluzen_flow/connections/oauth_session.py +232 -0
  250. revoluzen_flow/connections/odbc.py +180 -0
  251. revoluzen_flow/connections/paginator.py +218 -0
  252. revoluzen_flow/connections/runtime.py +118 -0
  253. revoluzen_flow/connections/sqlite_path.py +40 -0
  254. revoluzen_flow/connections/store.py +1397 -0
  255. revoluzen_flow/connections/tester.py +2386 -0
  256. revoluzen_flow/connections/vendor_db.py +138 -0
  257. revoluzen_flow/connections/verify_configs.json +77 -0
  258. revoluzen_flow/connections/versions.py +306 -0
  259. revoluzen_flow/connections/warehouse_clients.py +321 -0
  260. revoluzen_flow/connectors/__init__.py +17 -0
  261. revoluzen_flow/connectors/adapters/__init__.py +16 -0
  262. revoluzen_flow/connectors/adapters/odata.py +166 -0
  263. revoluzen_flow/connectors/adapters/rest.py +116 -0
  264. revoluzen_flow/connectors/ai_authoring.py +985 -0
  265. revoluzen_flow/connectors/attest.py +348 -0
  266. revoluzen_flow/connectors/cat.py +472 -0
  267. revoluzen_flow/connectors/cdc.py +308 -0
  268. revoluzen_flow/connectors/certify.py +122 -0
  269. revoluzen_flow/connectors/ci/cat_status.json +19 -0
  270. revoluzen_flow/connectors/ci/live_smoke.yml +54 -0
  271. revoluzen_flow/connectors/ci/source_watch_baseline.json +30 -0
  272. revoluzen_flow/connectors/ci/source_watch_status.json +119 -0
  273. revoluzen_flow/connectors/drafts.py +238 -0
  274. revoluzen_flow/connectors/jdbc.py +309 -0
  275. revoluzen_flow/connectors/jdbc_dialects.py +264 -0
  276. revoluzen_flow/connectors/manifest_v2.py +482 -0
  277. revoluzen_flow/connectors/manifests/airtable.json +30 -0
  278. revoluzen_flow/connectors/manifests/asana.json +41 -0
  279. revoluzen_flow/connectors/manifests/confluence.json +46 -0
  280. revoluzen_flow/connectors/manifests/datadog.json +51 -0
  281. revoluzen_flow/connectors/manifests/dynamics365.json +70 -0
  282. revoluzen_flow/connectors/manifests/elasticsearch.json +44 -0
  283. revoluzen_flow/connectors/manifests/elasticsearch.v2.json +177 -0
  284. revoluzen_flow/connectors/manifests/facebook_ads.json +46 -0
  285. revoluzen_flow/connectors/manifests/freshdesk.json +54 -0
  286. revoluzen_flow/connectors/manifests/github.json +54 -0
  287. revoluzen_flow/connectors/manifests/github.v2.json +150 -0
  288. revoluzen_flow/connectors/manifests/gitlab.json +54 -0
  289. revoluzen_flow/connectors/manifests/google_ads.json +55 -0
  290. revoluzen_flow/connectors/manifests/google_analytics.json +36 -0
  291. revoluzen_flow/connectors/manifests/hubspot.json +54 -0
  292. revoluzen_flow/connectors/manifests/hubspot.v2.json +194 -0
  293. revoluzen_flow/connectors/manifests/intercom.json +41 -0
  294. revoluzen_flow/connectors/manifests/jira.json +37 -0
  295. revoluzen_flow/connectors/manifests/jira.v2.json +139 -0
  296. revoluzen_flow/connectors/manifests/linkedin_ads.json +46 -0
  297. revoluzen_flow/connectors/manifests/mailchimp.json +42 -0
  298. revoluzen_flow/connectors/manifests/monday.json +26 -0
  299. revoluzen_flow/connectors/manifests/ms_teams.json +53 -0
  300. revoluzen_flow/connectors/manifests/netsuite.json +55 -0
  301. revoluzen_flow/connectors/manifests/notion.json +36 -0
  302. revoluzen_flow/connectors/manifests/notion.v2.json +140 -0
  303. revoluzen_flow/connectors/manifests/pagerduty.json +57 -0
  304. revoluzen_flow/connectors/manifests/pipedrive.json +46 -0
  305. revoluzen_flow/connectors/manifests/quickbooks.json +70 -0
  306. revoluzen_flow/connectors/manifests/rabbitmq.json +49 -0
  307. revoluzen_flow/connectors/manifests/redis.json +34 -0
  308. revoluzen_flow/connectors/manifests/salesforce.json +53 -0
  309. revoluzen_flow/connectors/manifests/salesforce.v2.json +155 -0
  310. revoluzen_flow/connectors/manifests/sap_odata.json +55 -0
  311. revoluzen_flow/connectors/manifests/sendgrid.json +48 -0
  312. revoluzen_flow/connectors/manifests/servicenow.json +62 -0
  313. revoluzen_flow/connectors/manifests/shopify.json +46 -0
  314. revoluzen_flow/connectors/manifests/shopify.v2.json +144 -0
  315. revoluzen_flow/connectors/manifests/slack.json +50 -0
  316. revoluzen_flow/connectors/manifests/slack.v2.json +142 -0
  317. revoluzen_flow/connectors/manifests/stripe.json +58 -0
  318. revoluzen_flow/connectors/manifests/stripe.v2.json +173 -0
  319. revoluzen_flow/connectors/manifests/twilio.json +49 -0
  320. revoluzen_flow/connectors/manifests/workday.json +52 -0
  321. revoluzen_flow/connectors/manifests/zendesk.json +43 -0
  322. revoluzen_flow/connectors/manifests/zoho_crm.json +61 -0
  323. revoluzen_flow/connectors/odbc_runtime.py +114 -0
  324. revoluzen_flow/connectors/openapi_import.py +149 -0
  325. revoluzen_flow/connectors/openapi_security.py +122 -0
  326. revoluzen_flow/connectors/openapi_source.py +172 -0
  327. revoluzen_flow/connectors/pgoutput.py +450 -0
  328. revoluzen_flow/connectors/request_connector.py +165 -0
  329. revoluzen_flow/connectors/rest_framework.py +1126 -0
  330. revoluzen_flow/connectors/source_watch.py +800 -0
  331. revoluzen_flow/connectors/vector_db.py +403 -0
  332. revoluzen_flow/connectors/wsdl_import.py +620 -0
  333. revoluzen_flow/contracts/__init__.py +39 -0
  334. revoluzen_flow/contracts/chain.py +82 -0
  335. revoluzen_flow/contracts/facts.py +153 -0
  336. revoluzen_flow/contracts/from_spec.py +137 -0
  337. revoluzen_flow/contracts/gate.py +85 -0
  338. revoluzen_flow/contracts/precommit.py +161 -0
  339. revoluzen_flow/contracts/schema.py +279 -0
  340. revoluzen_flow/contracts/service.py +84 -0
  341. revoluzen_flow/contracts/store.py +190 -0
  342. revoluzen_flow/contracts/verify.py +412 -0
  343. revoluzen_flow/credentials/__init__.py +4 -0
  344. revoluzen_flow/credentials/expiry.py +71 -0
  345. revoluzen_flow/credentials/models.py +77 -0
  346. revoluzen_flow/credentials/sensitive_fields.py +219 -0
  347. revoluzen_flow/credentials/store.py +232 -0
  348. revoluzen_flow/datastore/__init__.py +58 -0
  349. revoluzen_flow/datastore/models.py +241 -0
  350. revoluzen_flow/datastore/paths.py +173 -0
  351. revoluzen_flow/datastore/reader.py +526 -0
  352. revoluzen_flow/datastore/reconcile.py +198 -0
  353. revoluzen_flow/datastore/scaffold.py +240 -0
  354. revoluzen_flow/datastore/store.py +345 -0
  355. revoluzen_flow/datastore/table_monitor.py +253 -0
  356. revoluzen_flow/datastore/table_tests.py +208 -0
  357. revoluzen_flow/datastore/usage.py +454 -0
  358. revoluzen_flow/docs/NODE_REFERENCE.md +988 -0
  359. revoluzen_flow/docs/abstraction-boundary.md +126 -0
  360. revoluzen_flow/docs/ai-boundary-contract.md +207 -0
  361. revoluzen_flow/docs/ai-ops-contract.md +189 -0
  362. revoluzen_flow/docs/ai.md +123 -0
  363. revoluzen_flow/docs/api-explorer.md +130 -0
  364. revoluzen_flow/docs/api.md +634 -0
  365. revoluzen_flow/docs/architecture.md +125 -0
  366. revoluzen_flow/docs/benchmarks/postgres-competitive-2026-11.md +125 -0
  367. revoluzen_flow/docs/capability-matrix.md +140 -0
  368. revoluzen_flow/docs/compliance.md +102 -0
  369. revoluzen_flow/docs/connector-authoring.md +376 -0
  370. revoluzen_flow/docs/connectors/postgres.md +136 -0
  371. revoluzen_flow/docs/connectors/sqlserver.md +175 -0
  372. revoluzen_flow/docs/connectors.md +180 -0
  373. revoluzen_flow/docs/customer-faq.md +184 -0
  374. revoluzen_flow/docs/dashboard-metrics.md +300 -0
  375. revoluzen_flow/docs/deployment.md +367 -0
  376. revoluzen_flow/docs/design/00_overview.md +208 -0
  377. revoluzen_flow/docs/design/01_backend_lld.md +722 -0
  378. revoluzen_flow/docs/design/02_frontend_lld.md +574 -0
  379. revoluzen_flow/docs/design/03_functional_flows.md +652 -0
  380. revoluzen_flow/docs/design/backfill-ux-1.2.md +167 -0
  381. revoluzen_flow/docs/design/connection-pooling.md +189 -0
  382. revoluzen_flow/docs/design/consequence-grammar.md +279 -0
  383. revoluzen_flow/docs/design/decisions.md +109 -0
  384. revoluzen_flow/docs/design/execution-engines.md +142 -0
  385. revoluzen_flow/docs/design/executor-maturity-1.2.md +176 -0
  386. revoluzen_flow/docs/design/f01-manifest-v2.md +177 -0
  387. revoluzen_flow/docs/design/lineage-1.2.md +175 -0
  388. revoluzen_flow/docs/design/readme.md +43 -0
  389. revoluzen_flow/docs/design/sprint1-bulk-loaders.md +159 -0
  390. revoluzen_flow/docs/design/tier1-connector-uplift.md +146 -0
  391. revoluzen_flow/docs/design-data-wrangler-node.md +321 -0
  392. revoluzen_flow/docs/dev-guide.md +230 -0
  393. revoluzen_flow/docs/editions.md +69 -0
  394. revoluzen_flow/docs/eval-harness.md +122 -0
  395. revoluzen_flow/docs/examples/webhook-trigger.md +187 -0
  396. revoluzen_flow/docs/execution-timing.md +20 -0
  397. revoluzen_flow/docs/extend/build-a-connector.md +218 -0
  398. revoluzen_flow/docs/extend/build-a-node.md +118 -0
  399. revoluzen_flow/docs/faq.md +129 -0
  400. revoluzen_flow/docs/idempotency.md +113 -0
  401. revoluzen_flow/docs/install/database-drivers.md +340 -0
  402. revoluzen_flow/docs/install/security-hardening.md +247 -0
  403. revoluzen_flow/docs/nodes-and-canvas-reference.md +1965 -0
  404. revoluzen_flow/docs/nodes.md +85 -0
  405. revoluzen_flow/docs/performance.md +172 -0
  406. revoluzen_flow/docs/pipeline-documentation.md +73 -0
  407. revoluzen_flow/docs/product_facts/01_overview.md +35 -0
  408. revoluzen_flow/docs/product_facts/02_node_types.md +118 -0
  409. revoluzen_flow/docs/product_facts/03_editions.md +57 -0
  410. revoluzen_flow/docs/product_facts/04_concepts.md +96 -0
  411. revoluzen_flow/docs/product_facts/05_troubleshooting.md +76 -0
  412. revoluzen_flow/docs/product_facts/06_faq.md +88 -0
  413. revoluzen_flow/docs/product_facts/07_credentials.md +211 -0
  414. revoluzen_flow/docs/product_facts/08_connectors.md +131 -0
  415. revoluzen_flow/docs/product_facts/09_notifications.md +63 -0
  416. revoluzen_flow/docs/product_facts/10_ai_copilot.md +168 -0
  417. revoluzen_flow/docs/product_facts/11_workspace_rbac.md +75 -0
  418. revoluzen_flow/docs/product_facts/12_templates_expressions.md +79 -0
  419. revoluzen_flow/docs/product_facts/13_backup_recovery.md +76 -0
  420. revoluzen_flow/docs/product_facts/14_audit_lineage.md +97 -0
  421. revoluzen_flow/docs/product_facts/15_workers_scaling.md +69 -0
  422. revoluzen_flow/docs/product_facts/16_how_to.md +423 -0
  423. revoluzen_flow/docs/product_facts/17_where_to_find.md +246 -0
  424. revoluzen_flow/docs/product_facts/18_analytical_questions.md +404 -0
  425. revoluzen_flow/docs/product_facts/19_who_when_why.md +351 -0
  426. revoluzen_flow/docs/product_facts/20_pricing_resources.md +296 -0
  427. revoluzen_flow/docs/product_facts/21_multi_turn_dialogues.md +412 -0
  428. revoluzen_flow/docs/product_facts/22_real_world_scenarios.md +480 -0
  429. revoluzen_flow/docs/product_facts/23_code_generation.md +600 -0
  430. revoluzen_flow/docs/product_facts/24_decision_questions.md +604 -0
  431. revoluzen_flow/docs/product_facts/25_anti_patterns.md +488 -0
  432. revoluzen_flow/docs/quickstart.md +315 -0
  433. revoluzen_flow/docs/readme.md +60 -0
  434. revoluzen_flow/docs/releases/oss-release-checklist.md +106 -0
  435. revoluzen_flow/docs/releases/release-notes-1.0.md +150 -0
  436. revoluzen_flow/docs/reliability-1.2.md +246 -0
  437. revoluzen_flow/docs/repair-evaluation.md +326 -0
  438. revoluzen_flow/docs/roadmap/oss-1-1.md +264 -0
  439. revoluzen_flow/docs/roadmap/reliability-sprint.md +275 -0
  440. revoluzen_flow/docs/run-as-service.md +284 -0
  441. revoluzen_flow/docs/scaling.md +100 -0
  442. revoluzen_flow/docs/security/audit-2026-06-03.md +312 -0
  443. revoluzen_flow/docs/security-deployment.md +215 -0
  444. revoluzen_flow/docs/security-diagnostics.md +28 -0
  445. revoluzen_flow/docs/sop/README.md +73 -0
  446. revoluzen_flow/docs/sop/developer-operations.md +267 -0
  447. revoluzen_flow/docs/sop/go-live.md +265 -0
  448. revoluzen_flow/docs/sop/maintainer-operations.md +175 -0
  449. revoluzen_flow/docs/sop/security-response.md +119 -0
  450. revoluzen_flow/docs/sop/user-operations.md +264 -0
  451. revoluzen_flow/docs/sprint-b-cdc-runbook.md +87 -0
  452. revoluzen_flow/docs/steward/PROOF-2026-06-06/01-validation-run.txt +0 -0
  453. revoluzen_flow/docs/steward/PROOF-2026-06-06/02-memory-journal.jsonl +16 -0
  454. revoluzen_flow/docs/steward/PROOF-2026-06-06/05-test-suite-verbose.txt +0 -0
  455. revoluzen_flow/docs/steward/PROOF-2026-06-06/06-contract-snapshot.txt +0 -0
  456. revoluzen_flow/docs/steward/PROOF-2026-06-06/07-live-workspace-dryrun.txt +0 -0
  457. revoluzen_flow/docs/steward/PROOF-2026-06-06/09-memory-tab-journal.jsonl +12 -0
  458. revoluzen_flow/docs/steward/PROOF-2026-06-06/11-memory-verify-output.txt +0 -0
  459. revoluzen_flow/docs/steward/PROOF-2026-06-06/13-scenario-pack-v1.txt +0 -0
  460. revoluzen_flow/docs/steward/PROOF-2026-06-06/README.md +276 -0
  461. revoluzen_flow/docs/steward/PROOF-2026-06-08/overnight-verify.md +56 -0
  462. revoluzen_flow/docs/steward/architecture.md +742 -0
  463. revoluzen_flow/docs/steward/connector-health.md +132 -0
  464. revoluzen_flow/docs/steward/cost-tracking.md +182 -0
  465. revoluzen_flow/docs/steward/custom-rules.md +228 -0
  466. revoluzen_flow/docs/steward/governance.md +122 -0
  467. revoluzen_flow/docs/steward/memory-layer.md +254 -0
  468. revoluzen_flow/docs/steward/overview.md +626 -0
  469. revoluzen_flow/docs/steward/positioning.md +224 -0
  470. revoluzen_flow/docs/steward/quality-checks.md +155 -0
  471. revoluzen_flow/docs/steward/sample-memory.jsonl +16 -0
  472. revoluzen_flow/docs/steward/schema-drift.md +162 -0
  473. revoluzen_flow/docs/steward/validation-output.txt +88 -0
  474. revoluzen_flow/docs/steward/validation-scenarios.md +148 -0
  475. revoluzen_flow/docs/steward/volume-anomaly.md +86 -0
  476. revoluzen_flow/docs/storage.md +228 -0
  477. revoluzen_flow/docs/supported-models.md +107 -0
  478. revoluzen_flow/docs/testing.md +260 -0
  479. revoluzen_flow/docs/threat-model.md +227 -0
  480. revoluzen_flow/docs/trust.md +96 -0
  481. revoluzen_flow/docs/ui-language.md +137 -0
  482. revoluzen_flow/docs/user-guide.md +696 -0
  483. revoluzen_flow/docs/user-guides/connections.md +191 -0
  484. revoluzen_flow/docs/user-guides/external-triggers.md +251 -0
  485. revoluzen_flow/docs/user-guides/mainframe-and-legacy-files.md +236 -0
  486. revoluzen_flow/docs/user-guides/pipelines.md +624 -0
  487. revoluzen_flow/docs/user-guides/projects.md +302 -0
  488. revoluzen_flow/docs/user-guides/reports.md +78 -0
  489. revoluzen_flow/docs/user-guides/users-and-access.md +251 -0
  490. revoluzen_flow/docs/vs-airbyte.md +99 -0
  491. revoluzen_flow/docs/vs-talend.md +108 -0
  492. revoluzen_flow/docs/vs-visual-etl.md +96 -0
  493. revoluzen_flow/docs_static.py +98 -0
  494. revoluzen_flow/engine/__init__.py +4 -0
  495. revoluzen_flow/engine/admission.py +91 -0
  496. revoluzen_flow/engine/bulk_load/__init__.py +59 -0
  497. revoluzen_flow/engine/bulk_load/dialects/__init__.py +30 -0
  498. revoluzen_flow/engine/bulk_load/dialects/bigquery.py +233 -0
  499. revoluzen_flow/engine/bulk_load/dialects/mssql.py +254 -0
  500. revoluzen_flow/engine/bulk_load/dialects/postgres.py +299 -0
  501. revoluzen_flow/engine/bulk_load/dialects/redshift.py +232 -0
  502. revoluzen_flow/engine/bulk_load/dialects/snowflake.py +365 -0
  503. revoluzen_flow/engine/bulk_load/registry.py +70 -0
  504. revoluzen_flow/engine/bulk_load/runner.py +92 -0
  505. revoluzen_flow/engine/bulk_load/types.py +99 -0
  506. revoluzen_flow/engine/cancellation.py +341 -0
  507. revoluzen_flow/engine/checkpoint_store.py +384 -0
  508. revoluzen_flow/engine/connection_pool.py +291 -0
  509. revoluzen_flow/engine/engines.py +251 -0
  510. revoluzen_flow/engine/execution_log.py +641 -0
  511. revoluzen_flow/engine/execution_manager.py +1081 -0
  512. revoluzen_flow/engine/executor.py +2402 -0
  513. revoluzen_flow/engine/failure_class.py +233 -0
  514. revoluzen_flow/engine/global_governor.py +278 -0
  515. revoluzen_flow/engine/history_output.py +51 -0
  516. revoluzen_flow/engine/lookback.py +159 -0
  517. revoluzen_flow/engine/overlap.py +86 -0
  518. revoluzen_flow/engine/parameters.py +264 -0
  519. revoluzen_flow/engine/preview.py +85 -0
  520. revoluzen_flow/engine/queue/__init__.py +130 -0
  521. revoluzen_flow/engine/queue/descriptor.py +174 -0
  522. revoluzen_flow/engine/queue/inproc.py +87 -0
  523. revoluzen_flow/engine/queue/redis_queue.py +259 -0
  524. revoluzen_flow/engine/realtime.py +627 -0
  525. revoluzen_flow/engine/resource_monitor.py +116 -0
  526. revoluzen_flow/engine/retry_policy.py +247 -0
  527. revoluzen_flow/engine/run_time_limit.py +165 -0
  528. revoluzen_flow/engine/step_cache.py +316 -0
  529. revoluzen_flow/engine/step_output_store.py +243 -0
  530. revoluzen_flow/engine/subprocess_runner.py +402 -0
  531. revoluzen_flow/engine/sync_state_store.py +314 -0
  532. revoluzen_flow/engine/worker_pool.py +1319 -0
  533. revoluzen_flow/eval/__init__.py +18 -0
  534. revoluzen_flow/eval/cases.py +601 -0
  535. revoluzen_flow/eval/intent/__init__.py +6 -0
  536. revoluzen_flow/eval/intent/__main__.py +65 -0
  537. revoluzen_flow/eval/intent/cases.py +117 -0
  538. revoluzen_flow/eval/intent/runner.py +293 -0
  539. revoluzen_flow/eval/prompt_bank.csv +301 -0
  540. revoluzen_flow/eval/prompt_bank_README.md +162 -0
  541. revoluzen_flow/eval/repair/__init__.py +11 -0
  542. revoluzen_flow/eval/repair/__main__.py +90 -0
  543. revoluzen_flow/eval/repair/cases.py +665 -0
  544. revoluzen_flow/eval/repair/clients.py +174 -0
  545. revoluzen_flow/eval/repair/fresh_cases.py +898 -0
  546. revoluzen_flow/eval/repair/runner.py +656 -0
  547. revoluzen_flow/eval/repair/scoring.py +333 -0
  548. revoluzen_flow/eval/run.py +202 -0
  549. revoluzen_flow/eval/runner.py +885 -0
  550. revoluzen_flow/events/__init__.py +111 -0
  551. revoluzen_flow/events/bus.py +159 -0
  552. revoluzen_flow/events/consumers/__init__.py +21 -0
  553. revoluzen_flow/events/consumers/audit.py +114 -0
  554. revoluzen_flow/events/consumers/metrics.py +157 -0
  555. revoluzen_flow/events/factory.py +85 -0
  556. revoluzen_flow/events/in_process.py +374 -0
  557. revoluzen_flow/events/nats_bus.py +403 -0
  558. revoluzen_flow/events/types.py +327 -0
  559. revoluzen_flow/expression/__init__.py +5 -0
  560. revoluzen_flow/expression/resolver.py +437 -0
  561. revoluzen_flow/extraction/__init__.py +47 -0
  562. revoluzen_flow/extraction/engine.py +507 -0
  563. revoluzen_flow/extraction/events.py +285 -0
  564. revoluzen_flow/extraction/freshness.py +106 -0
  565. revoluzen_flow/extraction/manifest.py +112 -0
  566. revoluzen_flow/extraction/profile.py +214 -0
  567. revoluzen_flow/extraction/profiles/__init__.py +6 -0
  568. revoluzen_flow/extraction/profiles/endpoint_central_inventory.py +3 -0
  569. revoluzen_flow/extraction/schema_mapper.py +236 -0
  570. revoluzen_flow/extraction/session.py +101 -0
  571. revoluzen_flow/extraction/staging.py +144 -0
  572. revoluzen_flow/feature_flags.py +167 -0
  573. revoluzen_flow/flags/__init__.py +15 -0
  574. revoluzen_flow/flags/feature_flags.py +321 -0
  575. revoluzen_flow/folders/__init__.py +6 -0
  576. revoluzen_flow/folders/models.py +45 -0
  577. revoluzen_flow/folders/store.py +114 -0
  578. revoluzen_flow/frontend_dist/assets/AIPage-BYPVGmJh.js +1 -0
  579. revoluzen_flow/frontend_dist/assets/AIPage-DKegnQxk.css +1 -0
  580. revoluzen_flow/frontend_dist/assets/AccountPage-CvcS2tAT.js +1 -0
  581. revoluzen_flow/frontend_dist/assets/ActivityPage-DiBOgCn5.js +2 -0
  582. revoluzen_flow/frontend_dist/assets/Canvas-aJcYWw4p.js +18 -0
  583. revoluzen_flow/frontend_dist/assets/CatalogPicker-LlOV7Swa.js +1 -0
  584. revoluzen_flow/frontend_dist/assets/ChatPanel-B1Rmbh2q.js +11 -0
  585. revoluzen_flow/frontend_dist/assets/CodeEditorPanel-fti-K-cY.js +4 -0
  586. revoluzen_flow/frontend_dist/assets/ConfigPanel-D50wizn0.js +23 -0
  587. revoluzen_flow/frontend_dist/assets/ConnectionsPage-BkfNe3vr.js +8 -0
  588. revoluzen_flow/frontend_dist/assets/ConnectorIcons-CtcxUA-y.js +1 -0
  589. revoluzen_flow/frontend_dist/assets/CredentialsPage-Civ7fnck.js +1 -0
  590. revoluzen_flow/frontend_dist/assets/DataWranglerConfig-Bq7AUZLx.js +1 -0
  591. revoluzen_flow/frontend_dist/assets/DensityToggle-D_vc7f4K.js +1 -0
  592. revoluzen_flow/frontend_dist/assets/DetailDrawer-b7WTlgxL.js +5 -0
  593. revoluzen_flow/frontend_dist/assets/EmptyState-BmwJ2z6J.js +1 -0
  594. revoluzen_flow/frontend_dist/assets/ErrorBanner-DK-9ibrl.js +1 -0
  595. revoluzen_flow/frontend_dist/assets/ExecutionPoolPage-CuJu2POu.js +1 -0
  596. revoluzen_flow/frontend_dist/assets/ExecutionsPage-BL1EW0qq.js +6 -0
  597. revoluzen_flow/frontend_dist/assets/ExtractionPage-BOsvGayd.js +1 -0
  598. revoluzen_flow/frontend_dist/assets/FloatingAgentWidget-B4t9IIhD.js +25 -0
  599. revoluzen_flow/frontend_dist/assets/GlobalSearch-DMBtPW9d.js +1 -0
  600. revoluzen_flow/frontend_dist/assets/HelpPage-rxJG8CS-.js +15 -0
  601. revoluzen_flow/frontend_dist/assets/HeroCard-BOsNLJpN.js +1 -0
  602. revoluzen_flow/frontend_dist/assets/Icon-DxN4GgEB.js +1 -0
  603. revoluzen_flow/frontend_dist/assets/InlineConnectionForm-5QZ8BM5w.js +1 -0
  604. revoluzen_flow/frontend_dist/assets/LegacyFileSettings-BnZ_FBEC.js +4 -0
  605. revoluzen_flow/frontend_dist/assets/LineagePage-D6JrJtUP.js +1 -0
  606. revoluzen_flow/frontend_dist/assets/ModulesPanel-BzB1hpTx.js +1 -0
  607. revoluzen_flow/frontend_dist/assets/MoveToProjectButton-vnkZ7zP2.js +1 -0
  608. revoluzen_flow/frontend_dist/assets/NotificationsPage-CRh8nJmk.js +1 -0
  609. revoluzen_flow/frontend_dist/assets/OSSProductionPlaceholder-D-vkR9k_.js +1 -0
  610. revoluzen_flow/frontend_dist/assets/OllamaRecommendationBanner-BpoR-tDJ.js +1 -0
  611. revoluzen_flow/frontend_dist/assets/OnboardingWizard-DgPAFoF1.js +1 -0
  612. revoluzen_flow/frontend_dist/assets/OpenApiSecurityReview-xJk8X8Lr.js +1 -0
  613. revoluzen_flow/frontend_dist/assets/PipelinesPage-CKf4Zy-v.js +15 -0
  614. revoluzen_flow/frontend_dist/assets/PreviewPanel-C32L7tRg.js +1 -0
  615. revoluzen_flow/frontend_dist/assets/ProjectContextBar-BSGepbgh.js +1 -0
  616. revoluzen_flow/frontend_dist/assets/ProviderComparison-B4MSjt1U.js +1 -0
  617. revoluzen_flow/frontend_dist/assets/ReadOnlyBanner-eNYguvKN.js +1 -0
  618. revoluzen_flow/frontend_dist/assets/ReportsPage-DJGXEHxA.js +1 -0
  619. revoluzen_flow/frontend_dist/assets/ResizeHandle-mwbSI8pH.js +1 -0
  620. revoluzen_flow/frontend_dist/assets/RowActionButton-DQIunqva.js +1 -0
  621. revoluzen_flow/frontend_dist/assets/SettingsPage-CQFiD4wK.js +3 -0
  622. revoluzen_flow/frontend_dist/assets/Skeleton-DuGIRjgG.js +1 -0
  623. revoluzen_flow/frontend_dist/assets/StatusPill-jrbMCFBK.js +1 -0
  624. revoluzen_flow/frontend_dist/assets/StoragePage-CgUo90t0.js +4 -0
  625. revoluzen_flow/frontend_dist/assets/TableToolbar-DjQq6YGE.js +2 -0
  626. revoluzen_flow/frontend_dist/assets/TemplatesPage-CjDsK3ZX.js +1 -0
  627. revoluzen_flow/frontend_dist/assets/TimeAgo-BeeV8Lrr.js +1 -0
  628. revoluzen_flow/frontend_dist/assets/TransformHelper-tPKVox8f.js +8 -0
  629. revoluzen_flow/frontend_dist/assets/TriggersPage-CpyDnONN.js +6 -0
  630. revoluzen_flow/frontend_dist/assets/TrustPage-DpV4U9BF.js +3 -0
  631. revoluzen_flow/frontend_dist/assets/aiModels-Dg43c-RP.js +6 -0
  632. revoluzen_flow/frontend_dist/assets/apiExplorerDraft-ChblnxT2.js +1 -0
  633. revoluzen_flow/frontend_dist/assets/catalog-DD5ygzRr.js +1 -0
  634. revoluzen_flow/frontend_dist/assets/cost-CY27i4pI.js +1 -0
  635. revoluzen_flow/frontend_dist/assets/errorMessages-KxtxYOv6.js +1 -0
  636. revoluzen_flow/frontend_dist/assets/index-1mn3i83L.css +1 -0
  637. revoluzen_flow/frontend_dist/assets/index-DCmVwDXp.js +10 -0
  638. revoluzen_flow/frontend_dist/assets/index-Du7bxJKb.js +85 -0
  639. revoluzen_flow/frontend_dist/assets/markdown-L_vCpxjH.js +5 -0
  640. revoluzen_flow/frontend_dist/assets/revealNode-C3TarboN.js +1 -0
  641. revoluzen_flow/frontend_dist/assets/routePrefetch-BcihucMK.js +2 -0
  642. revoluzen_flow/frontend_dist/assets/triggerLabel-CSKClPlQ.js +1 -0
  643. revoluzen_flow/frontend_dist/assets/useEditorPreferences-BOpMX-PJ.js +1 -0
  644. revoluzen_flow/frontend_dist/assets/vendor-DVXy4IZ7.js +17 -0
  645. revoluzen_flow/frontend_dist/assets/vendor-flow-BZV40eAE.css +1 -0
  646. revoluzen_flow/frontend_dist/assets/vendor-flow-BsKbvqFG.js +7 -0
  647. revoluzen_flow/frontend_dist/assets/vendor-icons-BQwad7VI.js +141 -0
  648. revoluzen_flow/frontend_dist/assets/vendor-react-D2NtWQnz.js +49 -0
  649. revoluzen_flow/frontend_dist/connector-icons/README.md +31 -0
  650. revoluzen_flow/frontend_dist/connector-icons/adls.svg +1 -0
  651. revoluzen_flow/frontend_dist/connector-icons/bigquery.svg +1 -0
  652. revoluzen_flow/frontend_dist/connector-icons/cassandra.svg +1 -0
  653. revoluzen_flow/frontend_dist/connector-icons/chroma.svg +8 -0
  654. revoluzen_flow/frontend_dist/connector-icons/clickhouse.svg +1 -0
  655. revoluzen_flow/frontend_dist/connector-icons/cockroachdb.svg +1 -0
  656. revoluzen_flow/frontend_dist/connector-icons/couchbase.svg +1 -0
  657. revoluzen_flow/frontend_dist/connector-icons/databricks.svg +1 -0
  658. revoluzen_flow/frontend_dist/connector-icons/datadog.svg +6 -0
  659. revoluzen_flow/frontend_dist/connector-icons/dropbox.svg +10 -0
  660. revoluzen_flow/frontend_dist/connector-icons/dynamodb.svg +13 -0
  661. revoluzen_flow/frontend_dist/connector-icons/elasticsearch.svg +1 -0
  662. revoluzen_flow/frontend_dist/connector-icons/eventhub.svg +1 -0
  663. revoluzen_flow/frontend_dist/connector-icons/firebase.svg +1 -0
  664. revoluzen_flow/frontend_dist/connector-icons/gcs.svg +9 -0
  665. revoluzen_flow/frontend_dist/connector-icons/gdrive.svg +11 -0
  666. revoluzen_flow/frontend_dist/connector-icons/graphql.svg +1 -0
  667. revoluzen_flow/frontend_dist/connector-icons/gsheet.svg +1 -0
  668. revoluzen_flow/frontend_dist/connector-icons/jira.svg +1 -0
  669. revoluzen_flow/frontend_dist/connector-icons/kafka.svg +1 -0
  670. revoluzen_flow/frontend_dist/connector-icons/kinesis.svg +13 -0
  671. revoluzen_flow/frontend_dist/connector-icons/mariadb.svg +1 -0
  672. revoluzen_flow/frontend_dist/connector-icons/minio.svg +1 -0
  673. revoluzen_flow/frontend_dist/connector-icons/mongodb.svg +1 -0
  674. revoluzen_flow/frontend_dist/connector-icons/mssql.svg +1 -0
  675. revoluzen_flow/frontend_dist/connector-icons/mysql.svg +1 -0
  676. revoluzen_flow/frontend_dist/connector-icons/neo4j.svg +1 -0
  677. revoluzen_flow/frontend_dist/connector-icons/onedrive.svg +9 -0
  678. revoluzen_flow/frontend_dist/connector-icons/opensearch.svg +1 -0
  679. revoluzen_flow/frontend_dist/connector-icons/oracle.svg +1 -0
  680. revoluzen_flow/frontend_dist/connector-icons/pagerduty.svg +6 -0
  681. revoluzen_flow/frontend_dist/connector-icons/postgresql.svg +1 -0
  682. revoluzen_flow/frontend_dist/connector-icons/pulsar.svg +1 -0
  683. revoluzen_flow/frontend_dist/connector-icons/rabbitmq.svg +1 -0
  684. revoluzen_flow/frontend_dist/connector-icons/redis.svg +1 -0
  685. revoluzen_flow/frontend_dist/connector-icons/redshift.svg +14 -0
  686. revoluzen_flow/frontend_dist/connector-icons/s3.svg +13 -0
  687. revoluzen_flow/frontend_dist/connector-icons/salesforce.svg +1 -0
  688. revoluzen_flow/frontend_dist/connector-icons/sap.svg +16 -0
  689. revoluzen_flow/frontend_dist/connector-icons/slack.svg +1 -0
  690. revoluzen_flow/frontend_dist/connector-icons/snowflake.svg +1 -0
  691. revoluzen_flow/frontend_dist/connector-icons/splunk.svg +6 -0
  692. revoluzen_flow/frontend_dist/connector-icons/sqlite.svg +1 -0
  693. revoluzen_flow/frontend_dist/connector-icons/synapse.svg +1 -0
  694. revoluzen_flow/frontend_dist/connector-icons/trino.svg +1 -0
  695. revoluzen_flow/frontend_dist/connector-icons/twilio.svg +1 -0
  696. revoluzen_flow/frontend_dist/connector-icons/zendesk.svg +1 -0
  697. revoluzen_flow/frontend_dist/index.html +18 -0
  698. revoluzen_flow/frontend_dist/revoluzen-flow-logo-mark.png +0 -0
  699. revoluzen_flow/frontend_dist/revoluzen-flow-logo.png +0 -0
  700. revoluzen_flow/gateway/__init__.py +343 -0
  701. revoluzen_flow/gitcopy/__init__.py +17 -0
  702. revoluzen_flow/gitcopy/client.py +301 -0
  703. revoluzen_flow/gitcopy/files.py +328 -0
  704. revoluzen_flow/gitcopy/service.py +223 -0
  705. revoluzen_flow/gitcopy/settings.py +210 -0
  706. revoluzen_flow/gitcopy/store.py +152 -0
  707. revoluzen_flow/glossary/__init__.py +12 -0
  708. revoluzen_flow/glossary/store.py +240 -0
  709. revoluzen_flow/importers/__init__.py +2 -0
  710. revoluzen_flow/importers/dbt.py +530 -0
  711. revoluzen_flow/incidents/__init__.py +17 -0
  712. revoluzen_flow/incidents/policy.py +106 -0
  713. revoluzen_flow/incidents/service.py +295 -0
  714. revoluzen_flow/incidents/shared.py +127 -0
  715. revoluzen_flow/incidents/store.py +225 -0
  716. revoluzen_flow/intelligence/__init__.py +35 -0
  717. revoluzen_flow/intelligence/error_intel.py +558 -0
  718. revoluzen_flow/intelligence/execution_intel.py +471 -0
  719. revoluzen_flow/intelligence/flatten_engine.py +526 -0
  720. revoluzen_flow/intelligence/join_discovery.py +395 -0
  721. revoluzen_flow/intelligence/pre_validator.py +851 -0
  722. revoluzen_flow/intelligence/schema_contract.py +379 -0
  723. revoluzen_flow/intelligence/schema_detector.py +895 -0
  724. revoluzen_flow/intelligence/schema_history.py +228 -0
  725. revoluzen_flow/intelligence/schema_policy.py +616 -0
  726. revoluzen_flow/intelligence/type_normalization.py +705 -0
  727. revoluzen_flow/ir/__init__.py +8 -0
  728. revoluzen_flow/ir/docs.py +196 -0
  729. revoluzen_flow/ir/governance.py +119 -0
  730. revoluzen_flow/ir/lifecycle.py +151 -0
  731. revoluzen_flow/ir/migrations.py +297 -0
  732. revoluzen_flow/ir/node_metadata.py +255 -0
  733. revoluzen_flow/ir/plan_diff.py +203 -0
  734. revoluzen_flow/ir/preflight.py +186 -0
  735. revoluzen_flow/ir/published_refs.py +200 -0
  736. revoluzen_flow/ir/schema.py +689 -0
  737. revoluzen_flow/ir/spec.py +183 -0
  738. revoluzen_flow/ir/step_secrets.py +635 -0
  739. revoluzen_flow/ir/validator.py +390 -0
  740. revoluzen_flow/ir/versioning.py +1196 -0
  741. revoluzen_flow/ir/workflow_bin.py +311 -0
  742. revoluzen_flow/legacy_files/__init__.py +12 -0
  743. revoluzen_flow/legacy_files/codepages.py +166 -0
  744. revoluzen_flow/legacy_files/copybook.py +1202 -0
  745. revoluzen_flow/legacy_files/fixed_width.py +253 -0
  746. revoluzen_flow/legacy_files/landing.py +95 -0
  747. revoluzen_flow/legacy_files/records.py +221 -0
  748. revoluzen_flow/legacy_files/values.py +309 -0
  749. revoluzen_flow/licensing.py +81 -0
  750. revoluzen_flow/lifecycle/__init__.py +13 -0
  751. revoluzen_flow/lifecycle/store.py +193 -0
  752. revoluzen_flow/lineage/__init__.py +520 -0
  753. revoluzen_flow/lineage/openlineage.py +376 -0
  754. revoluzen_flow/main.py +2476 -0
  755. revoluzen_flow/marketplace/__init__.py +233 -0
  756. revoluzen_flow/monitoring/__init__.py +3 -0
  757. revoluzen_flow/monitoring/pipeline_health.py +242 -0
  758. revoluzen_flow/monitoring/status.py +148 -0
  759. revoluzen_flow/monitoring/store.py +481 -0
  760. revoluzen_flow/monitoring/timing.py +25 -0
  761. revoluzen_flow/nodes/__init__.py +3 -0
  762. revoluzen_flow/nodes/_column_mapping.py +66 -0
  763. revoluzen_flow/nodes/_kafka_positions.py +124 -0
  764. revoluzen_flow/nodes/_path_utils.py +77 -0
  765. revoluzen_flow/nodes/_remote_files.py +114 -0
  766. revoluzen_flow/nodes/_sftp.py +115 -0
  767. revoluzen_flow/nodes/_sync_mode_decl.py +141 -0
  768. revoluzen_flow/nodes/activities.py +2456 -0
  769. revoluzen_flow/nodes/advanced_transforms.py +371 -0
  770. revoluzen_flow/nodes/aggregate.py +173 -0
  771. revoluzen_flow/nodes/ai.py +428 -0
  772. revoluzen_flow/nodes/base.py +408 -0
  773. revoluzen_flow/nodes/cloud_files.py +1024 -0
  774. revoluzen_flow/nodes/cloud_storage.py +508 -0
  775. revoluzen_flow/nodes/control_extras.py +1216 -0
  776. revoluzen_flow/nodes/csv_source.py +53 -0
  777. revoluzen_flow/nodes/data_wrangler.py +738 -0
  778. revoluzen_flow/nodes/db_source.py +1373 -0
  779. revoluzen_flow/nodes/deduplicate.py +138 -0
  780. revoluzen_flow/nodes/file_node.py +1179 -0
  781. revoluzen_flow/nodes/filter_node.py +195 -0
  782. revoluzen_flow/nodes/flow_control.py +2741 -0
  783. revoluzen_flow/nodes/generic.py +279 -0
  784. revoluzen_flow/nodes/guardrails.py +166 -0
  785. revoluzen_flow/nodes/join.py +260 -0
  786. revoluzen_flow/nodes/local_table.py +815 -0
  787. revoluzen_flow/nodes/output.py +81 -0
  788. revoluzen_flow/nodes/pipeline_output.py +235 -0
  789. revoluzen_flow/nodes/quality.py +960 -0
  790. revoluzen_flow/nodes/reconcile.py +405 -0
  791. revoluzen_flow/nodes/registry.py +105 -0
  792. revoluzen_flow/nodes/retry_handler.py +96 -0
  793. revoluzen_flow/nodes/scd2.py +474 -0
  794. revoluzen_flow/nodes/sinks.py +2263 -0
  795. revoluzen_flow/nodes/sources.py +1328 -0
  796. revoluzen_flow/nodes/transform.py +122 -0
  797. revoluzen_flow/notifications/__init__.py +1 -0
  798. revoluzen_flow/notifications/models.py +32 -0
  799. revoluzen_flow/notifications/run_events.py +209 -0
  800. revoluzen_flow/notifications/service.py +746 -0
  801. revoluzen_flow/notifications/store.py +168 -0
  802. revoluzen_flow/openpgp/__init__.py +34 -0
  803. revoluzen_flow/openpgp/aead.py +251 -0
  804. revoluzen_flow/openpgp/algorithms.py +277 -0
  805. revoluzen_flow/openpgp/armor.py +210 -0
  806. revoluzen_flow/openpgp/credentials.py +105 -0
  807. revoluzen_flow/openpgp/keygen.py +165 -0
  808. revoluzen_flow/openpgp/keys.py +501 -0
  809. revoluzen_flow/openpgp/message.py +957 -0
  810. revoluzen_flow/openpgp/packets.py +445 -0
  811. revoluzen_flow/openpgp/signatures.py +545 -0
  812. revoluzen_flow/planner/__init__.py +4 -0
  813. revoluzen_flow/planner/ai_client.py +1144 -0
  814. revoluzen_flow/planner/ir_from_json.py +137 -0
  815. revoluzen_flow/planner/rule_planner.py +390 -0
  816. revoluzen_flow/planner/templates.py +450 -0
  817. revoluzen_flow/plugins/__init__.py +303 -0
  818. revoluzen_flow/pool/__init__.py +28 -0
  819. revoluzen_flow/pool/store.py +188 -0
  820. revoluzen_flow/projects/__init__.py +4 -0
  821. revoluzen_flow/projects/acl.py +143 -0
  822. revoluzen_flow/projects/models.py +95 -0
  823. revoluzen_flow/projects/store.py +147 -0
  824. revoluzen_flow/quality_rules/__init__.py +11 -0
  825. revoluzen_flow/quality_rules/store.py +248 -0
  826. revoluzen_flow/reports/__init__.py +22 -0
  827. revoluzen_flow/reports/builder/__init__.py +19 -0
  828. revoluzen_flow/reports/builder/catalog.py +329 -0
  829. revoluzen_flow/reports/builder/collect.py +1349 -0
  830. revoluzen_flow/reports/builder/deliver.py +276 -0
  831. revoluzen_flow/reports/builder/models.py +194 -0
  832. revoluzen_flow/reports/builder/render.py +468 -0
  833. revoluzen_flow/reports/builder/schedule.py +268 -0
  834. revoluzen_flow/reports/builder/store.py +274 -0
  835. revoluzen_flow/reports/cron_human.py +175 -0
  836. revoluzen_flow/reports/inventory.py +2108 -0
  837. revoluzen_flow/reports/inventory_docx.py +1209 -0
  838. revoluzen_flow/reports/inventory_pdf.py +1409 -0
  839. revoluzen_flow/runtime_config.py +290 -0
  840. revoluzen_flow/scheduling/__init__.py +4 -0
  841. revoluzen_flow/scheduling/lease.py +192 -0
  842. revoluzen_flow/scheduling/models.py +263 -0
  843. revoluzen_flow/scheduling/scheduler.py +1607 -0
  844. revoluzen_flow/scheduling/store.py +172 -0
  845. revoluzen_flow/security/__init__.py +25 -0
  846. revoluzen_flow/security/encryptor.py +414 -0
  847. revoluzen_flow/security/execution_codes.py +148 -0
  848. revoluzen_flow/security/migrate_existing.py +810 -0
  849. revoluzen_flow/security/route_posture_baseline.py +38 -0
  850. revoluzen_flow/security/sql_sandbox.py +335 -0
  851. revoluzen_flow/security/ssrf.py +207 -0
  852. revoluzen_flow/security/step_secret_routes.py +98 -0
  853. revoluzen_flow/security/win_acl.py +161 -0
  854. revoluzen_flow/seed_data/__init__.py +14 -0
  855. revoluzen_flow/seed_data/orders.csv +26 -0
  856. revoluzen_flow/sinks/__init__.py +26 -0
  857. revoluzen_flow/sinks/dedupe_store.py +300 -0
  858. revoluzen_flow/sinks/idempotency_helper.py +156 -0
  859. revoluzen_flow/sinks/tombstone.py +211 -0
  860. revoluzen_flow/state.py +169 -0
  861. revoluzen_flow/static/swagger-ui/LICENSES.md +29 -0
  862. revoluzen_flow/static/swagger-ui/favicon.png +0 -0
  863. revoluzen_flow/static/swagger-ui/redoc.standalone.js +1838 -0
  864. revoluzen_flow/static/swagger-ui/swagger-ui-bundle.js +2 -0
  865. revoluzen_flow/static/swagger-ui/swagger-ui.css +3 -0
  866. revoluzen_flow/steward/__init__.py +227 -0
  867. revoluzen_flow/steward/archeologist.py +481 -0
  868. revoluzen_flow/steward/cadence.py +256 -0
  869. revoluzen_flow/steward/connector_health.py +495 -0
  870. revoluzen_flow/steward/cost.py +421 -0
  871. revoluzen_flow/steward/coverage.py +108 -0
  872. revoluzen_flow/steward/foreseer.py +320 -0
  873. revoluzen_flow/steward/governance.py +299 -0
  874. revoluzen_flow/steward/ingest.py +220 -0
  875. revoluzen_flow/steward/lessons.py +550 -0
  876. revoluzen_flow/steward/memory.py +499 -0
  877. revoluzen_flow/steward/models.py +331 -0
  878. revoluzen_flow/steward/node_cardinality.py +331 -0
  879. revoluzen_flow/steward/notifier.py +256 -0
  880. revoluzen_flow/steward/null_rate.py +263 -0
  881. revoluzen_flow/steward/pii.py +286 -0
  882. revoluzen_flow/steward/quality.py +327 -0
  883. revoluzen_flow/steward/repeated_logic.py +172 -0
  884. revoluzen_flow/steward/row_delta.py +290 -0
  885. revoluzen_flow/steward/rules.py +394 -0
  886. revoluzen_flow/steward/schema_drift.py +380 -0
  887. revoluzen_flow/steward/settings.py +172 -0
  888. revoluzen_flow/steward/storage_intel.py +248 -0
  889. revoluzen_flow/steward/thresholds.py +94 -0
  890. revoluzen_flow/storage/__init__.py +5 -0
  891. revoluzen_flow/storage/backup.py +106 -0
  892. revoluzen_flow/storage/backup_scheduler.py +241 -0
  893. revoluzen_flow/storage/database.py +3542 -0
  894. revoluzen_flow/storage/database_factory.py +109 -0
  895. revoluzen_flow/storage/migrations.py +163 -0
  896. revoluzen_flow/storage/providers.py +392 -0
  897. revoluzen_flow/storage/storage_settings.py +214 -0
  898. revoluzen_flow/streams/__init__.py +29 -0
  899. revoluzen_flow/streams/connection.py +54 -0
  900. revoluzen_flow/streams/holds.py +94 -0
  901. revoluzen_flow/streams/pg_cdc.py +739 -0
  902. revoluzen_flow/streams/positions.py +139 -0
  903. revoluzen_flow/streams/rows.py +235 -0
  904. revoluzen_flow/telemetry/__init__.py +53 -0
  905. revoluzen_flow/telemetry/consent.py +83 -0
  906. revoluzen_flow/telemetry/sender.py +353 -0
  907. revoluzen_flow/templates/__init__.py +0 -0
  908. revoluzen_flow/templates/catalog_meta.py +186 -0
  909. revoluzen_flow/templates/gallery.py +18 -0
  910. revoluzen_flow/triggers/__init__.py +19 -0
  911. revoluzen_flow/triggers/chain.py +218 -0
  912. revoluzen_flow/triggers/file_listing.py +627 -0
  913. revoluzen_flow/triggers/file_watch.py +343 -0
  914. revoluzen_flow/triggers/gate.py +75 -0
  915. revoluzen_flow/triggers/store.py +272 -0
  916. revoluzen_flow/triggers/webhook_signing.py +139 -0
  917. revoluzen_flow/types/__init__.py +114 -0
  918. revoluzen_flow/types/canonical.py +256 -0
  919. revoluzen_flow/types/cast_safety.py +219 -0
  920. revoluzen_flow/types/drift.py +313 -0
  921. revoluzen_flow/types/from_mssql.py +323 -0
  922. revoluzen_flow/types/from_mysql.py +280 -0
  923. revoluzen_flow/types/from_oracle.py +306 -0
  924. revoluzen_flow/types/from_postgres.py +283 -0
  925. revoluzen_flow/types/policy.py +196 -0
  926. revoluzen_flow/types/to_mssql.py +234 -0
  927. revoluzen_flow/types/to_mysql.py +185 -0
  928. revoluzen_flow/types/to_oracle.py +202 -0
  929. revoluzen_flow/types/to_postgres.py +256 -0
  930. revoluzen_flow/variables/__init__.py +4 -0
  931. revoluzen_flow/variables/models.py +48 -0
  932. revoluzen_flow/variables/store.py +138 -0
  933. revoluzen_flow/workspaces/__init__.py +17 -0
  934. revoluzen_flow/workspaces/models.py +186 -0
  935. revoluzen_flow/workspaces/store.py +380 -0
  936. revoluzen_flow-1.0.1.dev0.dist-info/METADATA +826 -0
  937. revoluzen_flow-1.0.1.dev0.dist-info/RECORD +942 -0
  938. revoluzen_flow-1.0.1.dev0.dist-info/WHEEL +5 -0
  939. revoluzen_flow-1.0.1.dev0.dist-info/entry_points.txt +3 -0
  940. revoluzen_flow-1.0.1.dev0.dist-info/licenses/LICENSE +201 -0
  941. revoluzen_flow-1.0.1.dev0.dist-info/licenses/NOTICE +42 -0
  942. revoluzen_flow-1.0.1.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,724 @@
1
+ # Changelog
2
+
3
+ All notable changes to Revoluzen Flow are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ API stability policy: see `docs/api.md`. The HTTP API surface under `/api/*`
9
+ follows the compatibility rules documented there.
10
+
11
+ ## [Unreleased]
12
+
13
+ ### Added
14
+
15
+ - **Start a pipeline when a file arrives.** In a pipeline's Schedule dialog,
16
+ "A file arriving" watches a folder on the Flow server, on an SFTP server, on a
17
+ Windows file share, in Amazon S3 (or MinIO), Google Cloud Storage or Azure Blob
18
+ Storage. Each new file
19
+ whose name matches the pattern starts one run, with the file's path in the
20
+ parameter you choose. A file must stop changing for a set time before its run
21
+ starts, so one still being copied is not read half-written. What was seen is
22
+ remembered in the database, so a file never starts two runs, across restarts
23
+ and servers; a file replaced by a new version starts its own. Files already in
24
+ the folder are left alone unless you ask for them. Runs go one at a time, oldest
25
+ file first. "Check the folder now" shows what the trigger would see before you
26
+ save.
27
+
28
+ - **Run a pipeline after another one.** "Another pipeline finishing" starts it
29
+ when another pipeline succeeds, fails, or finishes either way. Runs started by
30
+ a schedule, a file, another pipeline or another application count; runs started
31
+ by hand do not. A loop is refused when it is saved, naming the pipelines in it,
32
+ and again at run time.
33
+
34
+ - **Signed calls to published endpoints.** An endpoint can require each call to
35
+ be signed with a secret Flow makes, shows once and keeps encrypted, in the open
36
+ Standard Webhooks format (`webhook-id`, `webhook-timestamp`,
37
+ `webhook-signature`). A changed call, a message already received, or one more
38
+ than 5 minutes old is refused. Works with or without an API key, and the
39
+ Triggers page writes the signing command for a terminal or PowerShell.
40
+
41
+ All three only ever run a published pipeline, at its published version, and
42
+ follow its overlap setting and run time limit. See
43
+ `docs/user-guides/pipelines.md` (Scheduling and triggers) and `docs/api.md`.
44
+
45
+ - **Windows file shares.** A new connection, **Windows File Share (SMB)**, reads
46
+ and writes `\\server\share` files with a saved sign-in (domain, user name,
47
+ password), the same whether Flow runs on Windows, Linux or Docker. Pick it in a
48
+ Source or Destination and the File step does the rest, so every format it reads
49
+ works on a share, including fixed-width text, COBOL copybook records, EBCDIC and
50
+ PGP-encrypted files; `*` and `?` in a file name read every matching file. A file
51
+ is written under a temporary name and renamed once complete, so a program
52
+ watching the folder never picks up half of it. Test connection signs in and
53
+ lists the folder. A file landing on a share can start a pipeline: choose "A
54
+ file arriving" and "A Windows file share" in the Schedule dialog, and each new
55
+ file starts one run with its full `\\server\share\...` path, which the File
56
+ step reads with the same connection. A file that the program writing it still
57
+ has open waits until it is closed. The client, `smbprotocol` (MIT, with
58
+ `pyspnego` and on Windows `sspilib`), now ships with Flow, and the connector
59
+ count is 67. See `docs/user-guides/mainframe-and-legacy-files.md`.
60
+
61
+ - **Kafka with a company's own certificate authority and client certificates.** A
62
+ Kafka connection that uses `SSL` or `SASL_SSL` now takes a CA certificate, so
63
+ Flow can reach brokers whose certificates the company signs itself, and a client
64
+ certificate with its private key (and the key's password, if it is locked) for
65
+ brokers that ask each client for one. They are pasted as text, so there is no
66
+ file to copy to the Flow server, and they reach both Kafka client libraries in
67
+ the Kafka Source, the Kafka Sink, Test connection and topic browsing. A
68
+ certificate that cannot be read, a wrong key password or a key that does not
69
+ belong to its certificate is named before Kafka is contacted. The private key and
70
+ its password are kept encrypted, never sent back to the browser and never
71
+ repeated in a message or a log line. Until now `SSL` trusted only the
72
+ certificates the computer trusts, and no client certificate could be given. See
73
+ `docs/nodes-and-canvas-reference.md` (Kafka Source).
74
+
75
+ - **Reports you design and schedule.** Insights > Reports used to offer one fixed
76
+ document. Now you choose the sections (runs, failures, successes, usage, storage,
77
+ AI use, environment, new builds, schedules, alerts, or a table you design), narrow
78
+ them to the period, projects and pipelines you care about, and save the report.
79
+ A saved report can be sent daily, weekly or monthly by email, Slack, Teams or
80
+ webhook, using the existing scheduler and notification settings. Each report keeps
81
+ a history of what went out, to whom, and why anything failed. The fixed inventory
82
+ document stays, as a starting point on the same page. See
83
+ `docs/user-guides/reports.md`.
84
+
85
+ - **The Bin for deleted pipelines.** Deleting a pipeline now moves it to the Bin
86
+ tab on the Pipelines page instead of removing it. It keeps its saved versions
87
+ and stays for 30 days (`REVOLUZEN_FLOW_BIN_RETENTION_DAYS`; `0` means never
88
+ removed automatically), then a daily job removes it for good. The Bin lives on
89
+ the server, so everyone in the workspace sees the same list, and the tab reads
90
+ it again each time it is opened: a pipeline someone else deleted or restored in
91
+ the meantime shows without reloading the page.
92
+
93
+ **Restore** brings a pipeline back as a draft, never published, with its
94
+ schedules back but paused. A name taken in the meantime gets a "(2)" suffix, and
95
+ a project or folder that is gone is replaced by Default or the project root; the
96
+ toast says which. **Delete forever** removes one at once, and admins can
97
+ **Empty Bin**. Deleting, restoring and removing need the Developer role, and
98
+ emptying needs Admin. Deleting a folder together with its pipelines goes to the
99
+ Bin too.
100
+
101
+ The API gains `GET /api/workflows/bin`, `POST /api/workflows/bin/{id}/restore`,
102
+ `DELETE /api/workflows/bin/{id}` and `DELETE /api/workflows/bin`.
103
+ `DELETE /api/workflows/{id}` now answers `{"deleted": true, "binned": true, ...}`,
104
+ and `?permanent=true` skips the Bin for scripts that must leave no copy (the app
105
+ has no button for it). Delete, restore and purge are recorded in the audit log.
106
+ A CDC pipeline gets new replication slots on restore and does not replay changes
107
+ made to its source while it was in the Bin.
108
+
109
+ - **Triggers page.** Workflows → Triggers lets another application start a
110
+ pipeline and pass it values: endpoints, API keys, and a ready-to-use command.
111
+ The runs appear on Executions with the trigger API, and the inventory report
112
+ lists endpoints and masked keys.
113
+
114
+ - **Credential expiry warnings.** Give a credential an expiry date and
115
+ administrators are warned on the bell and by email a week ahead, a day ahead
116
+ and when it expires. Settings → Notifications → Credential expiry warnings
117
+ turns them off.
118
+
119
+ - **Saved credentials fill a connection's fields.** Pick one under Saved
120
+ credential and the fields it holds fill themselves. A SaaS Connector step takes
121
+ a saved credential too.
122
+
123
+ - **The Copilot asks before drafting.** It asks where the data comes from and
124
+ where it goes, from the workspace's real connections, files and tables, and a
125
+ missing connection can be created in the chat.
126
+
127
+ - **`inspect_step_columns` Copilot tool.** Lists the columns a step receives, as
128
+ names and types only, so the agent can fix a renamed column instead of
129
+ guessing from an error message. It refuses if an upstream step could have a
130
+ side effect. The agent also gets guidance on repairing pipelines: draft instead
131
+ of describing, never guess a column, and leave a failing check in place.
132
+
133
+ - **Chained pipeline drafts.** `modify_pipeline_step` takes a `draft_id` to build
134
+ on an earlier edit, so a fix can span several steps. The editor now tells the
135
+ agent every step's id, which it needs to edit more than the selected step.
136
+
137
+ - **Repair evaluation for the Copilot.** `python -m revoluzen_flow.eval.repair`
138
+ runs broken pipelines through the real agent loop, then runs each draft on the
139
+ real engine against held-out data and answers computed in plain Python. It
140
+ scores repairs, whether failing checks were left alone, honest refusals and
141
+ false claims. CI gates the scripted ideal assistant at 100% and replays
142
+ recorded models. See `docs/repair-evaluation.md`.
143
+
144
+ - **The Copilot refuses to guess when repairing a pipeline.** An edit that
145
+ picks between columns, invents a replacement for one that is gone, or points a
146
+ source at something nobody named is refused until the person says which one.
147
+ Edits in one request now build on each other, a repair gets ten steps and must
148
+ end with an answer, and a refusal reaches the model whole. A draft test now
149
+ fails on a value that only breaks when rows are read.
150
+
151
+ - **The Copilot repairs from column names and types only.** It cannot see row
152
+ values, and an edit that writes a label, number or date nobody gave is refused.
153
+ A draft test's verdict is now `runs` rather than `passed`, and `output_checked`
154
+ says whether anything looked at the output.
155
+
156
+ - **More than one instance is now safe to run.** Two additions, together:
157
+
158
+ `REVOLUZEN_FLOW_ENABLE_SCHEDULER=0` makes a node API-only — it serves
159
+ requests without running the scheduler loop. Defaults on, so a single-node
160
+ install is unchanged.
161
+
162
+ `scheduling/lease.py` holds a durable single-row lease in the metadata
163
+ database; only the holder fires schedules. Acquire and renew are one
164
+ conditional `UPDATE` so two instances cannot both win between a read and a
165
+ write, the TTL is three tick intervals, and the holder renews every tick.
166
+ A clean `stop()` releases the lease so a standby takes over on its next
167
+ tick rather than waiting out the TTL.
168
+
169
+ Previously the scheduler tracked in-flight work in process-local dicts and
170
+ started unconditionally on every instance. Those dicts stop one process
171
+ double-running a schedule but say nothing about a second process, so two
172
+ instances behind a load balancer fired **every schedule twice** — silently,
173
+ with both runs looking legitimate. Verified with three instances over ten
174
+ ticks: ten firings, all from one node, where the old behaviour would have
175
+ produced thirty.
176
+
177
+ The lease fails closed. An instance that cannot reach the lease row does
178
+ not schedule, because missing a tick is recoverable and already alerted on
179
+ by schedule-miss detection, while a duplicate run can double-charge a
180
+ customer or duplicate rows in their warehouse.
181
+
182
+ Supported topology is now N API instances plus whichever one holds the
183
+ lease. A worker pool spanning machines is still not supported — see
184
+ `edition-matrix.md`.
185
+
186
+ - **Edition gate** — `revoluzen_flow/licensing.py` provides `is_plus()` and
187
+ `require_plus(feature)`, the first runtime enforcement of the Plus-only node
188
+ declarations in `edition-matrix.md`.
189
+
190
+ Those declarations previously had nothing behind them: CDC is listed
191
+ Plus-only in the edition matrix, in `ai/session_context.py` and in
192
+ anti-pattern rule 25, but `connectors/cdc.py` registered
193
+ `StepType.CDC_SOURCE` with no licence check and ran on free instances. No
194
+ node-level gate existed anywhere to follow — the `is_plus` checks in the
195
+ codebase were all in AI tools and catalog listings.
196
+
197
+ Detection fails closed: any import failure, missing `app_state` or
198
+ partially initialised licence manager reads as free, because an edition
199
+ check that defaults to paid when something breaks is not a check.
200
+ `PlusRequiredError` is its own type so the UI can offer an upgrade path, and
201
+ `engine/failure_class.py` maps it to `USER_INPUT` so the retry policy stops
202
+ — no number of attempts produces a licence.
203
+
204
+ The gate runs at **execution**, not registration, so a free instance still
205
+ shows the node and can build a pipeline against it. The catalog stays
206
+ identical across editions and the refusal names the feature when it runs.
207
+
208
+ CDC is gated. Vector DB sinks and the JDBC dialect registry were also
209
+ declared Plus-only with no enforcement; rather than add the gate, both
210
+ moved to OSS on 2026-10-23 — see below.
211
+
212
+ ### Changed
213
+
214
+ - **Two things that were declared but never built are gone.** The schedule type
215
+ `event`, with `event_trigger` and `event_source_id`, never fired; the API no
216
+ longer takes it. A row saved with it is read as the trigger it described
217
+ ("pipeline_completed" becomes "after another pipeline"), switched off, for
218
+ someone to check and turn on. The step type `webhook_trigger` had no
219
+ implementation and left the palette in May; it has left the step types too.
220
+ A saved pipeline that still holds one opens as before, rewritten to an API
221
+ source. Another system starts a pipeline through a published endpoint, which
222
+ can now require signed calls.
223
+
224
+ - **Vector DB sinks and the JDBC dialect registry are now OSS.** Both were
225
+ listed Plus-only and neither was ever enforced, so the choice was to add a
226
+ gate or drop the claim. Dropped it.
227
+
228
+ OSS already ships the entire local RAG stack — Ollama embeddings and a
229
+ SQLite-vec store — so charging to write pipeline output to a vector
230
+ database while embedding freely for our own features was the row a buyer
231
+ attacks first. The JDBC registry is the extensibility mechanism, and
232
+ Postgres, MySQL, MSSQL, SQLite and DuckDB all reach their databases
233
+ without touching it; gating it protected no revenue and only stopped
234
+ someone with an unusual database helping themselves. The *maintained*
235
+ enterprise dialects shipped through it (SAP HANA, Teradata, DB2, Informix)
236
+ stay Enterprise.
237
+
238
+ - **SSO is designated OSS**, and the matrix now says `planned` rather than
239
+ implying it ships — OIDC/SAML is not implemented in this repository at
240
+ all. Enterprise keeps SCIM provisioning and directory sync. The audit-log
241
+ row is clarified: the record, and the ability to read it, are OSS;
242
+ retention policy, signed export and SIEM formats are Enterprise.
243
+
244
+ - `edition-matrix.md` gains a **"which side does a new feature go on?"**
245
+ test, so the split is decided by rule rather than case by case. The
246
+ mechanism and the interface are OSS; maintained integrations,
247
+ administration-at-scale and governance over third parties are Enterprise.
248
+ Never gate correctness, and never gate security basics.
249
+
250
+ - **ELT on warehouses and the lakehouse.** `execute_sql_task` — the node that
251
+ fires SQL at a real connection rather than transforming in-memory — now
252
+ reaches `redshift`, `mssql`/`synapse`, `snowflake`, `bigquery` and
253
+ `databricks`, alongside the existing postgres, mysql/mariadb and sqlite.
254
+
255
+ Previously the matrix stopped at Postgres, MySQL and SQLite, so Revoluzen
256
+ Flow could *load into* Snowflake, BigQuery, Redshift and a lake but not
257
+ *transform in* them — the half of ELT that people mean by the word. The
258
+ dialect matrix is deliberately one function shared by Execute SQL and the
259
+ Lookup activity, so all of these arrived in one place.
260
+
261
+ This completes a Medallion pipeline end to end: land bronze as Parquet with
262
+ `adls_gen2_sink` or `s3_sink` (both emit `FORMAT PARQUET`, and parquet is
263
+ the default), build silver and gold with SQL running on Databricks or the
264
+ warehouse itself, then serve to SQL Server via `db_sink`, which routes
265
+ through the bulk loader. The intermediate layers never travel back through
266
+ the engine.
267
+
268
+ Drivers stay optional extras — `pip install revoluzen-flow[databricks]` and
269
+ friends — and a missing one now reports the install command rather than an
270
+ ImportError naming an unfamiliar module. Redshift needs no new dependency;
271
+ it is Postgres wire-compatible and uses psycopg2, differing only in its
272
+ default port.
273
+
274
+ ### Security
275
+
276
+ Fixes from an internal penetration test. Upgrade before exposing an instance
277
+ to anyone but yourself.
278
+
279
+ - **Roles are enforced on every route that runs or authors a pipeline.**
280
+ Running, replaying, testing and previewing pipelines, editing or testing
281
+ connections, uploads, imports, deployments and backfills now need the
282
+ developer role or above; approving needs an admin, and the approver is the
283
+ signed-in user, never a name sent with the request.
284
+ - **Pipeline SQL can no longer reach the instance's own secrets.** In server
285
+ mode, DuckDB runs with an allowlist: the data folder's working folders and
286
+ the files a pipeline names. The master key, the app database, backups and
287
+ the config folder are never on it. `REVOLUZEN_FLOW_SQL_SANDBOX=1|0` forces it
288
+ on or off. A SQL Transform must be a single statement.
289
+ - **Secrets stay masked.** The notification settings (SMTP password, webhook
290
+ URLs) need an admin and never return secrets; secret variables are masked in
291
+ every response.
292
+ - **Anonymous access is closed in server mode** for notifications, run
293
+ history and system information, and the Docker image and compose file now
294
+ start in server mode. A local-mode instance refuses requests that arrive
295
+ over the network, however it was started.
296
+ - **The first account on a server needs a one-time setup token**, printed in
297
+ the log at startup and saved as `SETUP_TOKEN.txt`.
298
+ - **Password-reset links** use `REVOLUZEN_FLOW_PUBLIC_URL` only, never the
299
+ request's own headers.
300
+ - **Cross-site requests** with an opaque (`null`) origin are refused on a
301
+ local install, and connection tests no longer block the server.
302
+ - Workspace admins stay in their own workspaces, admins cannot grant a role
303
+ above their own, comments are tied to their author and workspace, and
304
+ `/register` no longer reveals which emails have accounts.
305
+
306
+ ### Fixed
307
+
308
+ - **A Kafka Source read the same messages on every run.** Both Kafka readers
309
+ turned off Kafka's own position saving and never kept a position themselves,
310
+ so each run started again at the oldest message the topic still held, and an
311
+ append destination filled with copies. Each run now carries on after the last
312
+ message the previous successful run read. Flow keeps that position for each
313
+ pipeline step and saves it only when the whole run succeeds, so the messages of
314
+ a failed run are read again rather than lost: after a failure a message can
315
+ arrive twice, but none is skipped. Sample runs and Test Node leave the position
316
+ alone. The step no longer joins a consumer group, so two pipelines reading one
317
+ topic each get every message. A run also uses the brokers saved in the Kafka
318
+ connection (it ignored them and went to `localhost:9092` unless the step named
319
+ other servers), stops once it has caught up instead of waiting out its timeout,
320
+ and stops with a plain message when the topic does not exist or Kafka cannot be
321
+ reached, where it used to succeed with no rows. See
322
+ `docs/nodes-and-canvas-reference.md` (Kafka Source).
323
+
324
+ - **Kafka steps never signed in, so a secured cluster could not be used.** A Kafka
325
+ connection's security protocol, SASL mechanism, username and password reached no
326
+ Kafka client: the Kafka Source, the Kafka Sink, Test connection and topic
327
+ browsing all connected without signing in. They now sign in with `PLAIN`,
328
+ `SCRAM-SHA-256` or `SCRAM-SHA-512` over `SASL_PLAINTEXT` or `SASL_SSL`, with
329
+ either Kafka client library, and a refused sign-in stops the run with what Kafka
330
+ said. The password never appears in a message or a log line. The Kafka Sink also
331
+ read only the older `bootstrap_servers` key, so with a saved connection it wrote
332
+ to `localhost:9092`; it now uses the connection's brokers. It also finished as if
333
+ every message had gone even when Kafka took none; it now checks each message and
334
+ stops the run, saying how many were not written. Topic browsing now works with
335
+ the confluent-kafka add-on too.
336
+
337
+ - **The Kafka forms offered settings that runs ignored.** The Kafka Source's
338
+ Operation, Auto Offset Reset, Partition, Starting Offset and Value Deserializer,
339
+ and the Kafka Sink's Value Serializer and Compression, did nothing. The Source
340
+ now has "First run starts at": the oldest message Kafka keeps, or only new
341
+ messages. A step saved with Operation "consume from latest" keeps that choice.
342
+ The Sink's Compression now reaches Kafka. The other settings are gone, with the
343
+ steps' own broker and sign-in fields: a Kafka step uses a saved Kafka
344
+ connection, as every network step has since May. The Source form also shows the
345
+ step's saved read position with a Reset button, shows the defaults a run uses
346
+ (100 messages, not 1,000; a Sink batch of 500, not 16,384), and has a Timeout
347
+ field. Consumer Group is now optional.
348
+
349
+ - **Cron schedules that name a weekday ran a day late.** The scheduler counted
350
+ days from Monday, while the schedule dialog, the descriptions and the docs all
351
+ use standard cron, where 1 is Monday. A schedule set for Monday ran on Tuesday,
352
+ and `0 9 * * 1-5` ran Tuesday to Saturday. Now 0 and 7 are Sunday and 1 is
353
+ Monday. **Any such schedule moves one day earlier, to the day it has always
354
+ shown.** Hourly, daily, every-N-minutes and `weekly`-type schedules are not
355
+ affected.
356
+
357
+ - **A cron deployment could run twice in one minute.** The check for "already
358
+ ran" looked for a gap of under 30 seconds, and the next tick comes just over
359
+ 30 seconds later. A cron schedule or deployment now fires once in a matching
360
+ minute, and a long run that ends inside the next matching minute no longer
361
+ costs that minute its run.
362
+
363
+ - **The NATS event bus never worked against a real server.** With
364
+ `REVOLUZEN_FLOW_EVENT_BUS=nats`, creating the JetStream stream failed with
365
+ "invalid JSON": the stream's retention age was converted to nanoseconds
366
+ twice and overflowed. And every durable event was published a second time
367
+ over core NATS "for live fan-out", which the stream also captured, so each
368
+ event took two sequence numbers and a replay returned everything twice.
369
+ One publish now, and the age is passed in seconds as the client expects.
370
+ Found by running the end-to-end test against a server in CI for the first
371
+ time.
372
+
373
+ - **A folder that held pipelines could not be deleted.** The confirm said its
374
+ pipelines would be "permanently deleted", but the screen sent no mode and the
375
+ server will not guess what to do with them (409), so the user only saw a failure.
376
+ The screen now asks the server what is inside, says how many pipelines will be
377
+ moved to the Bin and how to get them back (they return to the project's top
378
+ level, since the folder is gone), and sends `force`. An empty folder deletes as
379
+ before.
380
+
381
+ - **Creating a pipeline in a folder never checked the folder.** The check passed
382
+ an argument the folder store does not take, and its error was swallowed, so a
383
+ pipeline could be created in a folder that does not exist or belongs to another
384
+ project. It now answers 404 (400 for another project's folder).
385
+
386
+ - **Anyone signed in could delete a folder and the pipelines in it.** Deleting a
387
+ pipeline takes the Developer role, but `DELETE /api/folders/{id}?force=true` only
388
+ asked for a signed-in user, so an analyst or viewer could send every pipeline in
389
+ a folder to the Bin (before the Bin, delete them). It takes the Developer role
390
+ now. Creating and renaming folders, and moving pipelines between them, still ask
391
+ only for a signed-in user.
392
+
393
+ - **A "+ Sub-folder" button that always failed.** Every folder row on the Projects
394
+ page offered it, but folders are one level deep and the server has always refused
395
+ a parent folder ("Sub-folders are not supported"), so it only produced an error.
396
+ The button is gone. "+ Folder" on a project is unchanged, and a folder nested in
397
+ older data is still shown.
398
+
399
+ - **Deleting a folder could send published pipelines to the Bin.** The row menu
400
+ offers Delete only for a draft, failed or archived pipeline, because a published
401
+ one has to be revoked first, but deleting the folder around it never looked at
402
+ status. A folder with a published pipeline in it now refuses to be deleted: the
403
+ screen names the pipelines to revoke before it asks anything, and
404
+ `DELETE /api/folders/{id}?force=true` answers 409 (`published_pipelines_in_folder`)
405
+ without deleting the drafts either. `move_to_root=true`, which keeps the
406
+ pipelines, is not affected.
407
+
408
+ - **The Copilot could return another pipeline's draft.** The idempotency key
409
+ ignored which pipeline was open, so the same edit on a second pipeline returned
410
+ the first pipeline's draft for 24 hours. The key now covers the workspace,
411
+ environment and selection, and draft tools are never served from the cache.
412
+
413
+ - **The write-tool dry-run gate never unlocked.** It forced dry runs until a user
414
+ had 3 successes but counted only live ones. Forced dry runs now count, their
415
+ stub results are no longer cached, and draft-only tools skip the gate for named
416
+ users, because a dry run only replaced a useful draft with a stub.
417
+
418
+ - **Local models could not edit a failing pipeline.** A request mentioning a
419
+ failure filled the eight-tool cap, leaving out the edit tool. The editor's
420
+ repair tools now always keep their slots.
421
+
422
+ - **Execute SQL on MySQL silently discarded writes.** `pymysql` connects with
423
+ `autocommit=False` and the branch never committed, so an `INSERT` or
424
+ `UPDATE` was rolled back when the connection closed — while the cursor
425
+ still reported a rowcount and the node still reported success. A write that
426
+ is lost this way is indistinguishable from one that worked. Commit
427
+ semantics are now pinned per driver and covered by tests, because they
428
+ genuinely differ: psycopg2 commits on context-manager exit, pymysql and
429
+ pyodbc need an explicit commit, Snowflake autocommits, and BigQuery and
430
+ Databricks have no interactive transaction to commit.
431
+
432
+ - **Six screens said one thing and the product did another.**
433
+ - Projects: a project card now has an edit (pencil) button. The Edit Project
434
+ dialog existed but nothing opened it, so a project's name, description,
435
+ colour and icon could never be changed.
436
+ - Dashboard, Avg duration: it now averages successful runs only, as its note
437
+ says. It used to average every finished run, failed ones included. The
438
+ Executions page's Avg Elapsed card reads the same figure and now says so.
439
+ - Dashboard, Pipeline status: the ring mixed run counts with a pipeline total.
440
+ It is now Run outcome mix and counts runs only; the slices add up to the run
441
+ count in the middle.
442
+ - Dashboard, empty state: a workspace with only hand-started runs read "no
443
+ runs yet". The Run volume chart, the ring and the greeting now count every
444
+ run; the Success rate card stays automated-only.
445
+ - Account: the subtitle no longer promises a list of active sessions.
446
+ - Help: Node Reference lists the 45 nodes in the editor's node panel rather
447
+ than 91 entries, says the panel is on the left, and says Delete Data removes
448
+ rows only. A test holds the list to the palette.
449
+
450
+ - **Six more screens said one thing and the product did another.**
451
+ - Pipelines: the Bin tab and its "moved to Bin, auto-removed after 30 days"
452
+ wording described a list kept in one browser while the server deleted the
453
+ pipeline for good. The Bin is now real and on the server (see **The Bin**
454
+ under Added). An archived pipeline also has a **Restore** button now (the
455
+ endpoint existed; no screen called it).
456
+ - Projects: the Archive button's tooltip no longer promises deletion after 30
457
+ days. Nothing deletes an archived project automatically.
458
+ - Delete Data: the settings no longer offer a "files" target, which was never
459
+ implemented and failed when the pipeline ran. A step saved with it still fails,
460
+ and its settings offer "Switch to deleting rows". File cleanup is the File
461
+ System node.
462
+ - Help: the connector strip counts the 66 connectors you can set up, not the 102
463
+ types the catalog registers, and tallies the certification mix over those 66.
464
+ - The Copilot's first-pipeline answer says the node panel is on the left and that
465
+ a node's settings open on double-click, along the bottom of the editor.
466
+ - Canvas tooltips now exist for Delete Data, File System, Execute SQL, Data
467
+ Profile and SaaS Connector, and the Data Quality tooltip no longer lists a
468
+ "unique" rule the node does not have. `docs/nodes.md` lists the 45 nodes.
469
+
470
+ - **The built-in templates' Data Quality steps checked nothing.** Eleven steps in
471
+ nine templates used setting names the Data Quality node does not read (`type`,
472
+ `columns`, `check`, `min`, `max`, `on_fail`, `on_failure`), and a rule the node
473
+ cannot read lets every row through. "Drop empty rows" kept the empty rows, steps
474
+ meant to fail the run never failed it, and a range or pattern check only tested
475
+ for a missing value. Every step now uses the node's own rules and On Failure
476
+ modes, and a test runs each one on data with a bad row.
477
+ - The node has no unique-value rule, so the steps that asked for one now check
478
+ what the node can: SharePoint → Managed Table fails the run when an id is
479
+ missing, and Daily sync drops rows with no id. CSV cleanup keeps its
480
+ Deduplicate step, which is what removes duplicate keys.
481
+ - Data quality + dead-letter queue sent rows to a Switch Case step that cannot
482
+ read the settings the template gave it, so the run failed there. Passing rows
483
+ now leave the Data Quality step by its Pass output to the clean table and
484
+ failing rows by its Reject output to the dead-letter table. The description no
485
+ longer promises a failure reason; the node does not record one.
486
+ - Medallion: the Silver step now drops rows that fail its rules. It was set to
487
+ mark them, which let them into Silver and the Gold totals; Bronze still keeps
488
+ every raw row.
489
+ - Inmon 3NF: the two key checks are named for what they do (the key columns are
490
+ filled in) instead of "PK" and "FK", and the description no longer says it
491
+ validates referential integrity.
492
+
493
+ - **The rest of the built-in templates did not use the settings their steps read.**
494
+ Besides the Data Quality steps, 92 steps in all 27 templates were given setting
495
+ names their node ignores, left out one it requires, or used a step or connector
496
+ the app no longer has. The editor refused to run them ("Missing required field"),
497
+ or a step quietly did something else. Every step now uses its node's own settings,
498
+ and tests hold each one to the node's list of settings and run each template on
499
+ small data with a bad row.
500
+ - First pipeline, the demo that promises real output on a fresh install, stopped
501
+ at its Derived Column step, which wants a list of columns where the template
502
+ gave it a SQL query. It runs now, as do the 19 other steps set up the same way.
503
+ - Managed Table steps (eight templates) used `schema` and `name`, which the node
504
+ does not read, so Run was refused with "Missing required field: table_name".
505
+ - Aggregate, Join and Union steps used `aggregations`, `left_key` / `right_key`
506
+ and `distinct` where the nodes read `functions`, `join_key` and `mode`, so a Join
507
+ stopped with "at least one join key is required". Two Aggregate steps grouped by
508
+ an expression, which the node reads as a column name; the day (DB →
509
+ Warehouse) and the month (Medallion) are now worked out in an earlier step.
510
+ - Database destinations asked for `upsert` with `key_columns`; the node's mode is
511
+ merge, on `merge_on`. Incremental database sources wrote `:last_run`, which
512
+ nothing fills in; they now use the source's incremental setting (a sync mode and
513
+ a watermark column). REST steps set `method`, `auth_type`, a pagination object
514
+ and a URL, none of which the node reads from a template; they now set the path
515
+ to add to the saved connection and the node's own cursor settings, and an
516
+ incremental REST step carries its cursor in the path. Oracle Fusion → Managed
517
+ Table named a connector that does not exist (Oracle Fusion is a kind of saved
518
+ connection, used with the REST source), and SharePoint → Managed Table now uses
519
+ the SharePoint source.
520
+ - Fan-out by region and AI classify + conditional route used the retired Switch
521
+ Case step; they use Switch now, one branch per case. AI classify had no labels
522
+ with example phrases, which the Semantic Router needs, and its description now
523
+ says that the built-in hash provider is a demo (it only matches an example
524
+ phrase word for word) and a real embedding provider should be chosen. Its Spam
525
+ archive wrote a CSV that every run overwrote; it is a Managed Table in append
526
+ mode.
527
+ - Medallion, Kimball, Data Vault and One Big Table wrote to a Warehouse
528
+ destination, which needs a database connection that a Parquet path cannot give.
529
+ They write to Managed Tables now, so they run with nothing to pick: Bronze and
530
+ the facts append, Silver and the Data Vault tables merge by key, the rest
531
+ replace. Medallion gained an "Add month" step for its Gold roll-up.
532
+ - A webhook cannot hand a pipeline rows: the request body becomes the pipeline's
533
+ parameters. Webhook → Flatten → Managed Table and Webhook → enrich → DB
534
+ started from a Source and a trigger node that do not exist. They now declare an
535
+ `event_id` parameter and fetch that event from the sender's API; the enrich
536
+ template reads its users from a second Source, which makes five nodes. Templates
537
+ can declare parameters.
538
+ - Pipeline failure → Slack alert had a SQL step with nothing feeding it; it now
539
+ reads the latest runs from the Executions API. Scheduled alert tested a
540
+ `row_count` column that does not exist; it now tests each job's failure count.
541
+ Slack messages use `{column}`; `{{column}}` came out with stray braces.
542
+ - Smaller: `has_header` is `header` on eight CSV sources; Lookup's Return Columns
543
+ is a list; Dedupe by ID keeps the newest row; Trim whitespace names columns the
544
+ sample orders.csv has; CSV cleanup no longer promises a trim step; the Data Vault
545
+ Dedupe steps set an Order By; the editor's own Aggregation starter asked for
546
+ `aggregations` where Aggregate reads `functions`; the Oracle BIP → SQL Server
547
+ scaffold's Data Quality step uses the node's rules.
548
+ - The pipeline check no longer warns that a Switch adds `_split_output` to a
549
+ destination when its rows leave by one of its named outputs, which strip it.
550
+ Scheduled alert and AI classify say what Slack Notify does: one message per run,
551
+ from the first row that reaches it, sent even when no row does.
552
+
553
+ - **Incremental database sources read every row on every run.** A source set to
554
+ incremental is meant to save the newest value it read and ask only for rows after
555
+ it the next time. The save looked for its working table under the wrong name,
556
+ failed without a word, and nothing was ever stored, so every scheduled run read and
557
+ loaded the whole table again and "Last cursor" in the source's settings stayed
558
+ empty. The value now comes from the rows the run loaded. It is saved only for a
559
+ run that succeeds and really loads rows: a Sample run, which reads a capped number
560
+ of rows and writes nothing, no longer moves it (once the save worked, it would
561
+ have sent the next real run past rows that were never loaded), and a warning is
562
+ logged when the cursor column is not in the result. A test runs the source twice
563
+ against a SQLite file with the real cursor store.
564
+ - **The editor refused to run a pipeline whose database source used a SQL query.**
565
+ Once a saved connection was picked, the pipeline check asked every database source
566
+ for a table ("Missing required field: table"), even in the default SQL Query mode
567
+ and with the query filled in, so Run stayed blocked however the source was set up.
568
+ The check read a setting that no panel writes any more. It now follows the source's
569
+ Mode, as the node does: a query source needs its query, a table source its table, a
570
+ stored-procedure source its procedure, and a database or warehouse destination its
571
+ table. Every database template can be run from the editor once its connection is
572
+ picked, and a test loads each of the 27 templates, picks their connections and Slack
573
+ webhook the way a user does, and expects no error.
574
+ - **Data Quality: three fixes in the node and its settings.**
575
+ - A row a check could not answer passed when the step was set to fail the run. A
576
+ missing amount under "between", "greater than", "equals" or "matches a pattern"
577
+ gives no answer. The node dropped such a row or sent it to Reject, but in Fail
578
+ mode it counted the row as good, so the run went through, and in Tag mode it left
579
+ the mark empty. Every mode now treats the row as failed: Fail stops the run, Tag
580
+ marks it false, and Split keeps it with the failures.
581
+ - The settings could not set up a "between", "in" or "not in" check. They had one
582
+ text box that saved what you typed as plain text, so "10,100" or "a,b" matched
583
+ nothing and every row was dropped. "Between" now has a low and a high box, "in"
584
+ and "not in" take a comma-separated list, and a number you type is saved as a
585
+ number (a column known to hold text keeps it as text). A check that was saved the
586
+ old way shows a note asking you to type it again.
587
+ - The pipeline check warned that any Data Quality step before a destination
588
+ "injects internal metadata columns". Only Tag mode (`__dq_passed`), the quality
589
+ score option (`__dq_score`) and Reject mode, when the rows do not leave by its
590
+ Pass or Reject output, add columns. The warning now appears only then and names
591
+ the columns.
592
+
593
+ - **A Data Quality rule the step could not use let every row through, silently.**
594
+ A rule with no column, a check the step does not have, or a value it cannot read
595
+ (a "between" without both limits, an empty "in" list, a pattern that is not text,
596
+ a length that is not a whole number) was treated as true for every row. The step
597
+ now stops the run before it checks any row, and the error names each rule by its
598
+ number, its column and what it needs. A pipeline saved from the old templates,
599
+ whose checks used setting names the step never read, now stops with "no column
600
+ chosen" instead of passing every row. The editor says the same before Run: the
601
+ pipeline check lists such a rule as an error, and a low limit above the high one
602
+ as a warning.
603
+
604
+ - **The editor now warns about Data Quality settings the step ignores.** A rule is
605
+ read as a column, a check and a value, and nothing else; the step reads only
606
+ its rules, On Failure, pass-rate threshold, score and profiling settings. The old
607
+ templates wrote more than that, and the step ignored it without a word: a rule
608
+ written as `check: between` with `min` and `max` ran as a plain "not empty", and
609
+ an `on_failure` setting left the step dropping rows instead of failing the run.
610
+ The pipeline check now lists each such key as a warning, saying what the rule or
611
+ step does as written. In the step's settings the same keys show under the rule
612
+ (or under On Failure) with a Remove button.
613
+
614
+ ### Changed
615
+
616
+ - `GET /api/connectors/cert-matrix` no longer returns the `by_tier` or
617
+ `production_total` aggregates. Certification is reported per connector:
618
+ each row carries `tier` and `cat_green`, and an attested connector also
619
+ carries `attested_at` and `attested_checks`.
620
+
621
+ A connector reaches an attested tier only once real vendor responses have
622
+ been recorded for it, so an unattested connector means "no fixtures
623
+ recorded yet" — not "this connector failed". An aggregate renders those
624
+ two states identically, and the reading that wins is the wrong one.
625
+ Callers that want a count can tally `rows` and own the framing.
626
+
627
+ - The Trust page drops the attestation totals and gains an **Attested**
628
+ column on the per-connector matrix, showing the date a connector's
629
+ acceptance suite last replayed green. Connectors without one show an
630
+ em-dash rather than a zero or a "not verified" badge.
631
+
632
+ ### Added
633
+
634
+ - **Source Watch** — daily detection that a connector's upstream API changed,
635
+ in `backend/revoluzen_flow/connectors/source_watch.py` and
636
+ `.github/workflows/source-watch.yml`.
637
+
638
+ Nothing previously could notice this. The acceptance suite replays recorded
639
+ cassettes, which proves our parsing against *the responses we recorded* and
640
+ by construction never contacts the vendor; the live-smoke allow-list is
641
+ empty. So the first party to learn that a connector had broken was whoever
642
+ it broke for.
643
+
644
+ Four signals, none of which needs a vendor account:
645
+ - the vendor advertises a newer API version than a connector is pinned to
646
+ - an endpoint one of our streams reads is gone from the vendor's own spec
647
+ - the vendor's published spec or changelog moved at all
648
+ - RFC 8594 `Deprecation` / `Sunset` headers, harvested passively from
649
+ responses the product already received — no extra request, and it covers a
650
+ customer's own internal APIs too
651
+
652
+ Connectors opt in with a `source_watch` block in their runtime manifest
653
+ (`docs/connector-authoring.md`). Eight ship with one — Asana, GitHub,
654
+ Intercom, Mailchimp, PagerDuty, Slack, Stripe and Twilio — each verified
655
+ against the vendor's live spec before being added. A connector without a
656
+ block is reported as `unwatched` rather than healthy. Read the state at
657
+ `GET /api/connectors/source-watch`, which makes no outbound call of its own.
658
+
659
+ Version severity reflects what the evidence supports: `critical` only when
660
+ the vendor no longer lists the version a connector pins, `warn` when a newer
661
+ version exists but ours is still supported, `info` when we pin the newest.
662
+ A probe narrowed to a single value cannot establish support at all, so it is
663
+ capped at `warn`. GitHub currently reports `warn` — 2026-03-10 has shipped
664
+ and 2022-11-28 remains supported.
665
+
666
+ Spec comparison reconciles base prefixes from either side, since Swagger 2
667
+ puts them in `basePath` (Slack `/api`, Mailchimp `/3.0`) while OpenAPI 3
668
+ puts them in `servers[].url` (Stripe `/`, Twilio none). JSON and YAML specs
669
+ are both read; an unparseable one degrades to fingerprint-only rather than
670
+ asserting that endpoints vanished.
671
+
672
+ - `.github/workflows/connector-attest.yml` re-runs the connector acceptance
673
+ suite twice weekly and on manifest or fixture changes. A green CAT result
674
+ older than 14 days stops counting, so without this every attested
675
+ connector silently decayed back to Beta.
676
+
677
+ ## [1.0.1] — 2026-10-18
678
+
679
+ First release published as **Revoluzen Flow**, by Revoluzen Private Limited.
680
+
681
+ The engine, connectors and UI are unchanged from the 1.0.x line; this release
682
+ renames the project and its published artifacts.
683
+
684
+ ### Changed
685
+
686
+ - Distribution is now `revoluzen-flow` on PyPI. The CLI entry point is
687
+ `revoluzen` (alias `rz`); `python -m revoluzen_flow` works as well.
688
+ - Python package is `revoluzen_flow`.
689
+ - Environment variables use the `REVOLUZEN_FLOW_` prefix, and the config
690
+ directory is `.revoluzen-flow`.
691
+ - Docker image is `revoluzen/flow`; the Compose service is `flow` and the
692
+ data volume is `revoluzen_flow_data`.
693
+ - OpenLineage events are emitted with the `revoluzen-flow` namespace and a
694
+ producer URI pointing at this repository.
695
+
696
+ ### Added
697
+
698
+ - `scripts/check_repo_coordinates.py`, run by the `architecture-invariants`
699
+ CI job. It fails the build when a self-referential GitHub slug disagrees
700
+ with `backend/revoluzen_flow/app_meta.py`, or when documentation tells a
701
+ reader to `cd` into a directory that `git clone` does not create.
702
+
703
+ ### Notes for existing installs
704
+
705
+ **This is a clean break. There is no migration path, and none is planned.**
706
+
707
+ The rename is total — nothing keeps the old spelling. In particular, these
708
+ carry stored or externally-observed state, and all of them changed:
709
+
710
+ - **Workflow node type** `fpulseNode` → `revoluzenFlowNode`. Recorded inside
711
+ every saved workflow, so pipelines saved by an earlier release will not
712
+ load.
713
+ - **Database file** `fpulse.db` → `revoluzen_flow.db` (and
714
+ `fpulse_events.db` → `revoluzen_flow_events.db`). An existing data
715
+ directory will not be found; the instance starts empty.
716
+ - **Session cookies** `fpulse_token` / `fpulse_session` / `fpulse_csrf` →
717
+ `revoluzen_flow_*`. Everyone is signed out once.
718
+ - **Prometheus metrics** `fpulse_*` → `revoluzen_flow_*`. Existing
719
+ dashboards and alert rules stop matching.
720
+ - **Bootstrap account** `admin@fpulse.local` → `admin@revoluzen.local`.
721
+ - **CSS classes, DOM data-attributes and custom events** — internal, but
722
+ listed for anyone who has written custom styling against them.
723
+
724
+ Treat an upgrade as a fresh install.