agentflow-runtime 1.5.0__tar.gz → 1.6.0__tar.gz

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 (131) hide show
  1. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/.gitignore +50 -5
  2. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/CHANGELOG.md +275 -59
  3. agentflow_runtime-1.6.0/PKG-INFO +280 -0
  4. agentflow_runtime-1.6.0/README.md +219 -0
  5. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/pyproject.toml +61 -9
  6. agentflow_runtime-1.6.0/requirements.txt +15 -0
  7. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/constants.py +1 -1
  8. agentflow_runtime-1.6.0/src/db_concurrency.py +24 -0
  9. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/cdc/normalizer.py +1 -1
  10. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/orchestration/dags/daily_batch.py +2 -1
  11. agentflow_runtime-1.6.0/src/processing/clickhouse_sink.py +210 -0
  12. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/event_replayer.py +26 -19
  13. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/flink_jobs/Dockerfile +1 -28
  14. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/flink_jobs/session_aggregator.py +3 -2
  15. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/flink_jobs/stream_processor.py +19 -10
  16. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/iceberg_sink.py +24 -3
  17. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/local_pipeline.py +57 -4
  18. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/outbox.py +62 -3
  19. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/alert_dispatcher.py +7 -9
  20. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/alerts/dispatcher.py +16 -19
  21. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/alerts/escalation.py +84 -24
  22. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/alerts/evaluator.py +19 -4
  23. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/alerts/history.py +30 -26
  24. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/analytics.py +41 -16
  25. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/auth/key_rotation.py +2 -2
  26. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/auth/manager.py +16 -4
  27. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/auth/middleware.py +7 -3
  28. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/auth/usage_table.py +2 -2
  29. agentflow_runtime-1.6.0/src/serving/api/egress_guard.py +89 -0
  30. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/main.py +5 -10
  31. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/rate_limiter.py +21 -11
  32. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/agent_query.py +29 -69
  33. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/alerts.py +26 -3
  34. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/batch.py +28 -82
  35. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/deadletter.py +163 -121
  36. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/lineage.py +53 -42
  37. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/search.py +1 -1
  38. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/slo.py +31 -10
  39. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/stream.py +21 -62
  40. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/webhooks.py +20 -2
  41. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/templates/admin.html +1 -1
  42. agentflow_runtime-1.6.0/src/serving/api/webhook_dispatcher.py +682 -0
  43. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/audit_publisher.py +13 -1
  44. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/backends/clickhouse_backend.py +226 -32
  45. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/backends/duckdb_backend.py +5 -3
  46. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/cache.py +15 -7
  47. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/catalog.py +50 -6
  48. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/contract_registry.py +18 -1
  49. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_engine.py +208 -0
  50. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/__init__.py +69 -0
  51. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/_sql_envelope.py +89 -0
  52. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/context.py +162 -0
  53. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/engine.py +85 -0
  54. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/graph.py +180 -0
  55. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/guards.py +210 -0
  56. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/nodes.py +200 -0
  57. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/parsing.py +98 -0
  58. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/prompts/__init__.py +26 -0
  59. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/prompts/generate_sql.txt +63 -0
  60. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/prompts/repair_sql.txt +34 -0
  61. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/provider.py +128 -0
  62. agentflow_runtime-1.6.0/src/serving/semantic_layer/nl_sql_engine/state.py +96 -0
  63. agentflow_runtime-1.6.0/src/serving/semantic_layer/query/engine.py +215 -0
  64. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query/entity_queries.py +6 -3
  65. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query/nl_queries.py +26 -9
  66. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query/sql_builder.py +56 -25
  67. agentflow_runtime-1.6.0/src/serving/semantic_layer/query/sql_guard.py +6 -0
  68. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/search_index.py +8 -2
  69. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/sql_guard.py +27 -0
  70. agentflow_runtime-1.5.0/PKG-INFO +0 -299
  71. agentflow_runtime-1.5.0/README.md +0 -238
  72. agentflow_runtime-1.5.0/requirements.txt +0 -4
  73. agentflow_runtime-1.5.0/src/serving/api/webhook_dispatcher.py +0 -424
  74. agentflow_runtime-1.5.0/src/serving/masking.py +0 -122
  75. agentflow_runtime-1.5.0/src/serving/semantic_layer/nl_engine.py +0 -189
  76. agentflow_runtime-1.5.0/src/serving/semantic_layer/query/engine.py +0 -82
  77. agentflow_runtime-1.5.0/src/serving/semantic_layer/query/sql_guard.py +0 -3
  78. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/LICENSE +0 -0
  79. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/__init__.py +0 -0
  80. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/__init__.py +0 -0
  81. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/cdc/__init__.py +0 -0
  82. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/connectors/__init__.py +0 -0
  83. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/connectors/mysql_cdc.py +0 -0
  84. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/connectors/postgres_cdc.py +0 -0
  85. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/producers/__init__.py +0 -0
  86. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/producers/event_producer.py +0 -0
  87. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/schemas/__init__.py +0 -0
  88. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/schemas/events.py +0 -0
  89. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/ingestion/tenant_router.py +0 -0
  90. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/logger.py +0 -0
  91. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/orchestration/__init__.py +0 -0
  92. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/orchestration/dags/__init__.py +0 -0
  93. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/__init__.py +0 -0
  94. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/flink_jobs/__init__.py +0 -0
  95. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/flink_jobs/checkpointing.py +0 -0
  96. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/flink_jobs/session_aggregation.py +0 -0
  97. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/tracing.py +0 -0
  98. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/transformations/__init__.py +0 -0
  99. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/processing/transformations/enrichment.py +0 -0
  100. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/__init__.py +0 -0
  101. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/monitors/__init__.py +0 -0
  102. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/monitors/freshness_monitor.py +0 -0
  103. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/monitors/metrics_collector.py +0 -0
  104. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/validators/__init__.py +0 -0
  105. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/validators/schema_validator.py +0 -0
  106. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/quality/validators/semantic_validator.py +0 -0
  107. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/__init__.py +0 -0
  108. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/__init__.py +0 -0
  109. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/alerts/__init__.py +0 -0
  110. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/auth/__init__.py +0 -0
  111. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/metrics.py +0 -0
  112. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/middleware/logging.py +0 -0
  113. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/middleware/metrics.py +0 -0
  114. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/middleware/tracing.py +0 -0
  115. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/__init__.py +0 -0
  116. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/admin.py +0 -0
  117. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/admin_ui.py +0 -0
  118. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/routers/contracts.py +0 -0
  119. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/security.py +0 -0
  120. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/telemetry.py +0 -0
  121. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/api/versioning.py +0 -0
  122. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/backends/__init__.py +0 -0
  123. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/db_pool.py +0 -0
  124. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/duckdb_connection.py +0 -0
  125. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/__init__.py +0 -0
  126. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/entity_type_registry.py +0 -0
  127. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query/__init__.py +0 -0
  128. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query/contracts.py +0 -0
  129. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query/metric_queries.py +0 -0
  130. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/query_engine.py +0 -0
  131. {agentflow_runtime-1.5.0 → agentflow_runtime-1.6.0}/src/serving/semantic_layer/schema_evolution.py +0 -0
@@ -72,7 +72,7 @@ node_modules/
72
72
  # Mutation testing output
73
73
  mutants/
74
74
 
75
- # Session notes (root-level temp .md created during Codex/Claude sessions).
75
+ # Local working notes (root-level temp .md created during dev sessions).
76
76
  # NOTE: BCG_audit.md was removed from this list on 2026-04-19 -
77
77
  # it was a release artifact, not a session note.
78
78
  /codex_res.md
@@ -93,12 +93,14 @@ integrations/agentflow_integrations/**/*.py[cod]
93
93
  agentflow_bench_debug*.duckdb*
94
94
  agentflow_demo_api.duckdb*
95
95
 
96
- # Local autopilot runtime state.
96
+ # Local autopilot tooling + runtime state (kept locally, not published).
97
97
  .autopilot/
98
+ /scripts/autopilot.ps1
99
+ /scripts/install-autopilot-task.ps1
100
+ /tests/unit/test_autopilot_runner.py
98
101
 
99
- # Operator scratch notes at the repo root (user-owned audit prompts/results;
100
- # codex audit F-6). Ignored so the autopilot clean-tree gate and git status
101
- # stay quiet without touching the files themselves.
102
+ # Local scratch notes at the repo root (audit prompts/results). Ignored so
103
+ # the clean-tree gate and git status stay quiet without touching the files.
102
104
  /p[0-9].md
103
105
  /p[0-9]_res*.md
104
106
  /p_res*.md
@@ -106,3 +108,46 @@ agentflow_demo_api.duckdb*
106
108
 
107
109
  # Security scan workdir (generated by .github/workflows/security.yml safety job)
108
110
  .tmp-security/
111
+
112
+ # Internal working notes / autonomous-session artifacts — kept locally, not published.
113
+ # These are process/handoff/scratch docs, not product or engineering documentation.
114
+ /AGENT_STATE.md
115
+ /AUTOPILOT.md
116
+ /BACKLOG.md
117
+ /help.md
118
+ /res.md
119
+ /all-open-questions-closure-plan.md
120
+ /close-gaps-plan.md
121
+ /road-to-9.8.md
122
+ /desc_for_julia.md
123
+ /fable_*.md
124
+ /next-session-*.md
125
+ /second-opinion-*.md
126
+ /.pi/
127
+ /.workflow/
128
+ /res/
129
+ docs/dv2-multi-branch/kimi_*.md
130
+ docs/dv2-multi-branch/RECORDING_DAY.md
131
+ docs/dv2-multi-branch/pitch.md
132
+ docs/dv2-multi-branch/brief.md
133
+ docs/operations/local-verification-matrix.md
134
+ docs/release-readiness-archive/
135
+ docs/codex-tasks/
136
+ docs/plans/codex-archive/
137
+ docs/lessons/
138
+ docs/audits/
139
+ docs/exploration/
140
+ docs/audit-history.md
141
+ docs/SESSION_HANDOFF.md
142
+ docs/dv2-multi-branch/SESSION_HANDOFF*.md
143
+ docs/customer-discovery-*.md
144
+ docs/pricing-validation-plan.md
145
+ docs/v1-1-interview-prep.md
146
+ docs/v1-1-research.md
147
+ docs/operations/autonomous-compact-safe-process.md
148
+ docs/operations/external-gate-evidence-intake.md
149
+ docs/operations/external-pen-test-attestation-handoff.md
150
+ docs/operations/generated-external-gate-pack-*.md
151
+ docs/operations/guarded-autopilot-*.md
152
+ docs/operations/immutable-retention-evidence-handoff.md
153
+ docs/operations/security-evidence-template.md
@@ -4,6 +4,236 @@ All notable changes to AgentFlow are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.6.0] - 2026-07-02
8
+
9
+ ### Added — vault-side PII governance on the engine (ADR 0006 Phase 2, executed 2026-07-02)
10
+
11
+ - **New `warehouse/agentflow/dv2/governance/`** — ClickHouse RBAC as the PII
12
+ boundary for the DV2 vault, replacing the removed app-level string-parse
13
+ gate with access control on resolved columns: `dv2_analyst` (cross-branch
14
+ analytics, fail-closed allow-list, contact-PII columns never granted) and
15
+ per-jurisdiction `dv2_pii_officer__<branch>` roles (own branch's
16
+ `bv_customer_mdm` view + personal satellite only), plus row policies
17
+ scoping the shared `rv.hub_customer` to the officer's jurisdiction (with
18
+ the mandatory catch-all keeping non-officer visibility independent of
19
+ `users_without_row_policies_can_read_rows`).
20
+ - **`bv_customer_mdm__*` views run `SQL SECURITY DEFINER`** so column-limited
21
+ grants on the views work without exposing the underlying
22
+ `sat_customer_personal__1c__*` satellites to readers.
23
+ - **`marts.customer_360` is PII-free by contract** — the cross-branch
24
+ materialized mart no longer selects `first_name`/`last_name`/`email`
25
+ (copying jurisdiction-bound PII past the column grants at build time);
26
+ `pii_source` metadata stays.
27
+ - **Verified live** against ClickHouse 26.7 (32/32 adversarial probes): every
28
+ PII shape denied for `dv2_analyst` — including the three historical
29
+ bypass forms of the removed app gate, two of which are not even expressible
30
+ on this engine — officers bounded to their jurisdiction, admin unaffected,
31
+ re-apply idempotent. Includes a root-caused ergonomic limitation of filter
32
+ pushdown over column-limited DEFINER views and its PII-safe subquery
33
+ workaround. Evidence: `docs/perf/vault-pii-governance-verify-2026-07-02.md`.
34
+ - `infrastructure/dv2/clickhouse-sts.yaml` sets
35
+ `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1"` so the stand admin can apply
36
+ RBAC DDL; `tests/unit/test_dv2_governance_ddl.py` pins the boundary
37
+ structure (PII columns never granted, every satellite classified, catch-all
38
+ in sync with officer roles, DEFINER on the views, mart stays PII-free).
39
+
40
+ ### Changed — ClickHouse is the shipped serving engine (ADR 0006 Phase 1, executed 2026-07-02)
41
+
42
+ - **`config/serving.yaml` defaults to `backend: clickhouse`.** `make demo`,
43
+ `docker-compose.yml`, and `docker-compose.prod.yml` bring the ClickHouse
44
+ service up by default (the `--profile clickhouse` gate is removed; the API
45
+ container `depends_on` its healthcheck). Rollback is config-only
46
+ (`SERVING_BACKEND=duckdb`). Tests stay pinned to DuckDB
47
+ (`tests/conftest.py`), and DuckDB remains the local-dev / test store.
48
+ - **The local pipeline writes the serving store** — new
49
+ `src/processing/clickhouse_sink.py`: when the configured backend is
50
+ ClickHouse, every validated event mirrors its serving-table writes and its
51
+ `pipeline_events` journal row there (dead-letter rows included), after the
52
+ DuckDB commit. A configured-but-unreachable ClickHouse fails loudly instead
53
+ of letting the demo serve a frozen seed.
54
+ - **Upserts are ReplacingMergeTree row versions.** The four mutable serving
55
+ tables move from `MergeTree` to `ReplacingMergeTree` versioned by a
56
+ `MATERIALIZED af_updated_at` column (invisible to `SELECT *`, inserts, and
57
+ `table_columns`); every backend read carries the `final=1` setting so
58
+ queries always see the latest version. **Existing demo ClickHouse volumes
59
+ must be dropped and re-seeded** (engine changes don't apply to existing
60
+ tables; the demo store is disposable by design).
61
+ - **The freshness-critical event scan goes through the serving backend.** New
62
+ `QueryEngine.fetch_pipeline_events()`; the webhook dispatcher (which also
63
+ drives metric-cache invalidation) and the `/v1/stream/events` SSE scan
64
+ delegate to it instead of reaching into the embedded DuckDB connection — so
65
+ event-driven freshness works when the writer is out-of-process and the
66
+ engine is external. Verified live against a real ClickHouse 26.7 server:
67
+ cross-process burst moved the served revenue metric, SSE streamed
68
+ ClickHouse-only events, upsert dedup read back one latest-version row
69
+ (`docs/perf/clickhouse-serving-verify-2026-07-02.md`).
70
+ - **Transpile safety net:** `ClickHouseBackend._translate_sql` now fails
71
+ closed if any table reference — including the tenant schema qualifier
72
+ applied by `_scope_sql` *before* the rewrite — does not survive the
73
+ duckdb→clickhouse transpile or does not re-parse. Guards the
74
+ rewrite-after-guard seam that produced the historical PII bypasses, now for
75
+ tenant isolation.
76
+ - **Fixed (found by the live verification):** the ClickHouse backend sent the
77
+ session-database URL parameter on the `CREATE DATABASE` bootstrap statement,
78
+ which fails with `UNKNOWN_DATABASE` on a bare server (Docker's
79
+ `CLICKHOUSE_DB` pre-creation masked it).
80
+ - **Helm:** new `serving.*` values wire `SERVING_BACKEND` /
81
+ `CLICKHOUSE_*` env (password via `existingSecret`); the chart default stays
82
+ the safe single-node DuckDB profile because the chart ships no ClickHouse
83
+ service. **ADR 0009** records the honest scaling gate: the control plane
84
+ (webhook queue, alert history, outbox, usage) is an embedded per-pod DuckDB
85
+ store, so `replicaCount`/`autoscaling` stay pinned even on the ClickHouse
86
+ profile until it is externalized.
87
+
88
+ ### Removed
89
+
90
+ - **The serving-layer PII protection is removed — it guarded columns that do not
91
+ exist.** The demo serving warehouse holds no PII: `users_enriched` and
92
+ `orders_v2` (and every other serving table) carry only analytics columns
93
+ (aggregates, ids, timestamps) — none of the fields declared in the former
94
+ `config/pii_fields.yaml` (`email`, `phone`, `full_name`, `ip_address`,
95
+ `shipping_address`) exist in the catalog entity contracts or the physical DDL.
96
+ So the interim NL→SQL `assert_no_pii_access` deny-gate and the entity-path
97
+ `redact_entity` masker were operating on a surface that is never present in the
98
+ demo — defense-in-depth over an empty set. Both are deleted, along with
99
+ `src/serving/pii_policy.py`, `config/pii_fields.yaml`, their CI coverage /
100
+ mutation gates, the helm `piiFields` config, and the `X-PII-Masked` emission
101
+ (the versioned header stays reserved; the generic version-transform that would
102
+ strip it for older clients is unchanged). This also un-breaks the rule-based
103
+ `SELECT *` user/order lookups the deny-gate had been rejecting. The earlier
104
+ SQL-lineage masker (`src/serving/masking.py`, removed in the same cycle) is
105
+ likewise gone. **Real contact PII lives only in the DV2 business vault**
106
+ (`warehouse/agentflow/dv2/business_vault/bv_customer_mdm__*.sql`), and its
107
+ governance belongs engine-side there — ClickHouse row/column policies, tracked
108
+ as ADR 0006 Phase 2 — not in a dialect-pinned string parse in the serving tier.
109
+
110
+ ### Changed
111
+
112
+ - **NL→SQL LLM path now routes through the GraceKelly orchestration API**
113
+ (`nl_engine._llm_translate`), not a direct provider SDK. It POSTs to
114
+ `${GRACEKELLY_URL}/api/v1/orchestrate` with the target model
115
+ (`GRACEKELLY_NL_SQL_MODEL`, default `claude-sonnet-5`); GraceKelly owns model
116
+ execution (browser-backed). LLM mode is gated on `GRACEKELLY_URL` (was
117
+ `ANTHROPIC_API_KEY`); engine detection across the query package, analytics, and
118
+ agent-query telemetry was realigned to match. The previous direct
119
+ `claude-sonnet-4-20250514` call is removed. The shipped demo still runs the
120
+ **rule-based** translator (GraceKelly is opt-in, unset in deploy configs);
121
+ when configured, GraceKelly serves `claude-sonnet-5`.
122
+ - **Serving engine decision: fixed on ClickHouse** (ADR 0006 + 0007). The demo
123
+ serving default moves DuckDB → ClickHouse, with DuckDB demoted to the
124
+ local-dev / test and compatibility store. This unblocks engine-native bounded
125
+ PII (ClickHouse row/column policies) and real Kubernetes horizontal API
126
+ scaling. Recorded as a decision and staged in `docs/clickhouse-cutover-plan.md`;
127
+ the config/compose/Helm cutover itself is **not yet executed**.
128
+
129
+ ### Added
130
+
131
+ - **DV2 raw vault migrated from ClickHouse to PostgreSQL** with a cloud
132
+ supplier / product reference (`warehouse/agentflow/dv2/`). Hubs, links, and
133
+ satellites are emitted in a PostgreSQL dialect (`argMax` → `DISTINCT ON`,
134
+ `splitByString` → `split_part`); both ingestion feeds (the X5 loader and the
135
+ reference loader) repoint to a shared, parameterized `pg_vault_writer`; and
136
+ OLTP → vault promotion runs as an in-database `INSERT … SELECT` now that OLTP
137
+ and the vault share one engine. The ClickHouse dialect regenerates
138
+ byte-for-byte and is retained for optional mart-serving. Each generated
139
+ `INSERT` is parsed by `sqlglot` in `tests/unit/test_dv2_postgres_ingestion.py`
140
+ to assert every interpolated column exists in the committed DDL. (#91)
141
+ - **PyIceberg sink backed by a real MinIO object store** — the REST catalog
142
+ now writes through `S3FileIO` to `s3://agentflow-lake/warehouse` (the same
143
+ bucket the Flink path uses) instead of an ephemeral `/tmp/warehouse`
144
+ `HadoopFileIO`. A self-contained `docker-compose.iceberg.yml` (MinIO +
145
+ bucket-init + REST catalog) and env-overridable credentials in
146
+ `config/iceberg.yaml` make the local catalog object-store-backed; a no-Docker
147
+ guard asserts an `s3://` warehouse never triggers a local `mkdir`. (#92)
148
+ - **Event-driven OLTP → vault freshness via PostgreSQL `LISTEN`/`NOTIFY`** —
149
+ `AFTER INSERT/UPDATE` triggers on each `ops_<branch>` table emit
150
+ `pg_notify('dv2_vault_refresh', …)`, and a guarded listener runs an
151
+ idempotent promote on each event (push, not polling), the PostgreSQL
152
+ equivalent of the ClickHouse `MaterializedPostgreSQL` CDC path. Lag is
153
+ observed on the server clock (`db_now`) to stay free of host/container
154
+ clock skew. The driver-agnostic core is covered no-Docker by
155
+ `tests/unit/test_dv2_freshness_listen_notify.py`. (#93)
156
+ - OpenSSF Scorecard $0 supply-chain security posture channel:
157
+ `.github/workflows/scorecard.yml` (`ossf/scorecard-action@v2.4.3`) runs on
158
+ push to `main`, weekly, and on branch-protection changes with top-level
159
+ `read-all` permissions and a least-privilege analysis job
160
+ (`security-events`/`id-token` writes only), publishes the public Scorecard
161
+ result, and uploads SARIF to Code scanning. Shape-pinned by
162
+ `tests/unit/test_scorecard_workflow.py`. A companion
163
+ `docs/operations/openssf-security-posture.md` documents the channel and
164
+ carries a prepared OpenSSF Best Practices self-assessment for operator
165
+ submission. These are posture signals only — explicitly NOT a third-party
166
+ penetration-test attestation; backlog item 22 stays N/A and unclaimed.
167
+ - Backlog item 19 reopened with a real evidence channel: the production
168
+ source is the operator-owned Neon Postgres backing VacancyRadar
169
+ (`public.vacancies`), recorded with an honest solo-org decision record in
170
+ `docs/operations/cdc-production-onboarding.md`. New dispatch-only
171
+ `.github/workflows/cdc-production-capture.yml` builds the repo's Debezium
172
+ Kafka Connect image, reads connection material only from Actions secrets
173
+ via FileConfigProvider, snapshots the approved table scope over TLS, writes
174
+ an evidence artifact, and always tears down the connector, publication, and
175
+ replication slot (shape tests pin dispatch-only, secret sourcing, sslmode,
176
+ the teardown trap, and always-upload). The first run waits on the operator
177
+ enabling Logical Replication on the Neon project (irreversible
178
+ `wal_level` flip).
179
+ - Backlog item 21 closed with real evidence under an operator-amended
180
+ hardware class: `.github/workflows/benchmark-arm.yml` (dispatch-only) runs
181
+ the canonical benchmark on the free GitHub-hosted arm64 runner for public
182
+ repositories (`ubuntu-24.04-arm`, Neoverse-N2, 4 vCPU). First real run
183
+ (27012731848) recorded 554 requests / 0 failures, aggregate p50 6 ms /
184
+ p99 150 ms — every entity gate passed. Evidence in
185
+ `docs/perf/arm-server-benchmark-2026-06-05.md` plus raw artifacts; shape
186
+ tests pin dispatch-only/runner-label/artifact upload, and the job carries
187
+ an A06 dependency-profile target (`perf`). No `c8g.4xlarge` claim is made.
188
+
189
+ ### Changed
190
+
191
+ - Dependency maintenance batch (consolidated from eight Dependabot PRs): the
192
+ Docker `python` base digest, `cp-kafka-connect-base` 7.9.7 → 7.9.8,
193
+ `apache-flink` 2.2.1 → 2.3.0 (validated by the Flink smoke job), and the SDK
194
+ `vitest` / `schemathesis` bumps, plus the GitHub Pages action major bumps
195
+ (`checkout` v7, `configure-pages` v6, `upload-pages-artifact` v5,
196
+ `deploy-pages` v5) — all SHA-pinned and validated on `main` by the Deploy
197
+ Pages and Flink Smoke runs. (#94)
198
+ - Production CDC onboarding, PMF/pricing evidence, a production-hardware
199
+ benchmark, and an external pen-test attestation are documented as out of
200
+ scope for the current plan. Their acceptance criteria require external
201
+ counterparties (production source owners, real customers, production-grade
202
+ hardware, a third-party tester) that are deliberate non-goals for this
203
+ reference project. The gated claims remain explicitly unmade: production CDC
204
+ is not enabled, PMF/pricing is not validated, no production-hardware results
205
+ exist, and no third-party attestation exists. Status is summarized in
206
+ `docs/release-readiness.md`.
207
+
208
+ ### Security
209
+
210
+ - First OpenSSF Scorecard cycle acted on — published score **5.8 → 7.0**,
211
+ open Code-scanning findings **163 → 53**, every remainder classified
212
+ accepted-open (see `docs/operations/openssf-security-posture.md` §4 for the
213
+ fixed/accepted-open split):
214
+ - Every `uses:` in all 19 workflows (99 references, 20 unique actions) is
215
+ pinned to a full commit SHA with a trailing `# <version>` comment that
216
+ Dependabot's `github-actions` ecosystem keeps updating. The convention is
217
+ enforced by the new `tests/unit/test_workflow_action_pinning.py`;
218
+ per-workflow shape tests now assert action identity (prefix) instead of
219
+ mutable tags.
220
+ - Top-level `permissions: contents: read` added to the five workflows that
221
+ ran on the default token (`staging-deploy`, `e2e`, `contract`,
222
+ `cdc-production-capture`, `benchmark-arm`), and
223
+ `container-attestation.yml` no longer grants
224
+ `packages`/`id-token`/`attestations` writes at the top level — they moved
225
+ to the two operator-dispatched signing jobs, so the every-PR `build-smoke`
226
+ job runs read-only (pinned by a new shape test).
227
+ - All four Dockerfile `FROM` lines are digest-pinned to their current
228
+ manifest-list digests, and the Dependabot `docker` ecosystem now covers
229
+ every Dockerfile directory (`directories:` list) so the pins keep moving
230
+ with upstream tags.
231
+ - `warehouse/agentflow/dv2/loaders/x5_retail_hero/requirements.txt` floors
232
+ raised: `pydantic>=2.9` (GHSA-mr82-8j83-vxmv ReDoS range started at the
233
+ old 2.0 floor) and `tqdm>=4.66.3` (PYSEC-2017-74 and the 2024 CLI
234
+ injection both fall below it). Resolution-floor fixes only; runtime code
235
+ is unchanged.
236
+
7
237
  ## [1.5.0] - 2026-06-05
8
238
 
9
239
  ### Added
@@ -37,7 +267,7 @@ All notable changes to AgentFlow are documented in this file.
37
267
  observe the `hashed_key_count_exceeds_guidance` warning (the warning still
38
268
  emits; only the capture goes blind). An autouse fixture now re-points the
39
269
  package logger at a fresh uncached proxy per test, making the file
40
- order-independent. Found while reproducing the 2026-06-03 codex audit F-1
270
+ order-independent. Found while reproducing the 2026-06-03 audit F-1
41
271
  claim that the broad no-Docker full-repo pytest run is unreliable on this
42
272
  host: on the canonical `.venv` the run completes with a normal summary and
43
273
  leaves no orphan uvicorn child (the audit ran the shadow system Python),
@@ -111,7 +341,7 @@ All notable changes to AgentFlow are documented in this file.
111
341
 
112
342
  ### Changed
113
343
 
114
- - `scripts/` is now part of the CI Ruff gate (2026-06-03 codex audit F-2:
344
+ - `scripts/` is now part of the CI Ruff gate (2026-06-03 audit F-2:
115
345
  release/benchmark/backup/security tooling had drifted to 20 lint errors and
116
346
  12 unformatted files that CI never checked). The 12 drifted scripts were
117
347
  reformatted (no semantic changes), import order and `datetime.UTC` usages
@@ -163,7 +393,7 @@ All notable changes to AgentFlow are documented in this file.
163
393
  spec are unchanged (`export_openapi.py --check` green).
164
394
  - The ClickHouse serving backend now translates DuckDB-flavored
165
395
  semantic-layer SQL through a sqlglot parse → AST rewrite → generate
166
- pipeline instead of the former regex chain (PR #41; closes audit_kimi
396
+ pipeline instead of the former regex chain (PR #41; closes audit finding
167
397
  H-C2 in full — the earlier literal-masking commit was the narrow fix).
168
398
  String literals are preserved structurally by the parser, and
169
399
  unparseable or multi-statement SQL now fails loudly as
@@ -416,7 +646,7 @@ All notable changes to AgentFlow are documented in this file.
416
646
  - New module `src/serving/api/auth/usage_table.py` holds
417
647
  `ensure_usage_table` / `record_usage` / `usage_by_tenant`, which used
418
648
  to live alongside the ASGI middleware in
419
- `src/serving/api/auth/middleware.py`. Closes Kimi audit L-C4
649
+ `src/serving/api/auth/middleware.py`. Closes audit L-C4
420
650
  ("DB utilities don't belong in a middleware file"). Public callers
421
651
  go through `AuthManager.*` shim methods unchanged; the only direct
422
652
  importer was `tests/unit/test_audit_publisher.py`, repointed to the
@@ -425,7 +655,7 @@ All notable changes to AgentFlow are documented in this file.
425
655
 
426
656
  ### Performance
427
657
 
428
- - The two Flink hot-path findings from `audit_kimi_25_05_26.md` are closed
658
+ - The two Flink hot-path findings from the 2026-05 internal audit are closed
429
659
  now that the runtime is on 2.2.1 (they were gated on the PR #23 upstream
430
660
  wait). M-C3: `ValidateAndEnrich` emits `(event_id, payload)` pairs and the
431
661
  dedup `key_by` reads the key from the tuple, dropping the second
@@ -443,7 +673,7 @@ All notable changes to AgentFlow are documented in this file.
443
673
  events to two enriched outputs. The JSON-in-MapState layout is
444
674
  deliberately unchanged (checkpoint compatible).
445
675
  - `scripts/perf/auth_bench.py` + `docs/perf/auth-bench-2026-05-26.md`
446
- — perf-baseline microbench closing two deferred Kimi audit findings.
676
+ — perf-baseline microbench closing two deferred audit findings.
447
677
  Measured `authenticate()` worst-case at production `bcrypt_rounds=12`:
448
678
  N=5 hit-last p95 = 1.9 s, N=20 hit-last p95 = 8.1 s (exceeds the
449
679
  1100 ms POST load gate). M-C4 stays partial-deferred — steady-state
@@ -502,7 +732,7 @@ All notable changes to AgentFlow are documented in this file.
502
732
  counter branch and the `/metrics` exposure round trip.
503
733
  - 6 new unit tests in `tests/unit/test_cdc_connector_configs.py`
504
734
  exercise `src.ingestion.connectors.{mysql_cdc,postgres_cdc}`
505
- pure-Python config builders. Closes Kimi audit R4: both files
735
+ pure-Python config builders. Closes audit R4: both files
506
736
  went from 0% to 100% combined (line+branch) unit coverage; total
507
737
  `src.ingestion` rose 82% → ~85%. Tests pin the operational knobs
508
738
  the `cdc-lag` runbook depends on (snapshot mode, heartbeat
@@ -514,7 +744,7 @@ All notable changes to AgentFlow are documented in this file.
514
744
  - `.github/workflows/contract.yml` now triggers on
515
745
  `infrastructure/terraform/**`, `sdk-ts/**`, and `Dockerfile*`
516
746
  paths in addition to the existing src/sdk/pyproject/workflows
517
- set. Closes Kimi audit R2 and removes the last remaining
747
+ set. Closes audit R2 and removes the last remaining
518
748
  `--admin merge` workaround from session 18 for changes outside
519
749
  the Python tree.
520
750
  - `.github/workflows/ci.yml` main coverage gate
@@ -534,7 +764,7 @@ All notable changes to AgentFlow are documented in this file.
534
764
  `build-push-sign-attest` + `attest-and-sign` jobs are gated
535
765
  behind `github.event_name == 'workflow_dispatch'` so a PR can
536
766
  never accidentally fire the ghcr.io push / cosign sign path.
537
- Closes Kimi audit R6. A new
767
+ Closes audit R6. A new
538
768
  `test_container_attestation_workflow_runs_smoke_on_pull_request`
539
769
  unit test asserts the trigger paths, the PR-event gate, and
540
770
  push/load shape. Local Docker Desktop 29.4.0 smoke verified the
@@ -548,7 +778,7 @@ All notable changes to AgentFlow are documented in this file.
548
778
  `int()` / `float()`) fixed with `cast()` at the JSON boundary.
549
779
  mypy is now clean on all 98 source files including
550
780
  `checkpointing`, `session_aggregation`, `session_aggregator`,
551
- `stream_processor`. Closes Kimi audit R7.
781
+ `stream_processor`. Closes audit R7.
552
782
 
553
783
  ### Fixed
554
784
 
@@ -563,7 +793,7 @@ All notable changes to AgentFlow are documented in this file.
563
793
  fails. The DuckDB insert is now retried in isolation; the audit
564
794
  publish runs exactly once after a successful insert and a publish
565
795
  failure is logged as `audit_publish_failed` instead of re-driving
566
- the retry loop. Closes Kimi audit H-C3. Two regression tests in
796
+ the retry loop. Closes audit H-C3. Two regression tests in
567
797
  `tests/unit/test_audit_publisher.py` pin the contract:
568
798
  `test_record_usage_no_duplicate_insert_when_publish_raises` and
569
799
  `test_record_usage_skips_publish_when_all_inserts_fail`.
@@ -573,7 +803,7 @@ All notable changes to AgentFlow are documented in this file.
573
803
  warning (`search_index_initial_rebuild_failed`) instead of
574
804
  aborting startup. The 60-second periodic rebuilder (which already
575
805
  catches its own exceptions) is still scheduled, so the search
576
- surface can recover without a process restart. Closes Kimi audit
806
+ surface can recover without a process restart. Closes audit
577
807
  M-C1. Regression test:
578
808
  `tests/unit/test_lifespan_search_resilience.py::test_lifespan_survives_search_rebuild_failure`.
579
809
 
@@ -586,7 +816,7 @@ All notable changes to AgentFlow are documented in this file.
586
816
  literals (including `''`-escaped quotes) are masked with sentinel
587
817
  placeholders and restored after the rewrites. The `INTERVAL '...'`
588
818
  rewrite still runs first against raw SQL so quoted intervals
589
- continue to collapse. Closes part of Kimi audit H-C2 (literal
819
+ continue to collapse. Closes part of audit H-C2 (literal
590
820
  corruption vector). Seven regression tests in
591
821
  `tests/unit/test_clickhouse_backend.py::TestTranslateSqlLiteralProtection`
592
822
  pin the contract against `::FLOAT`, `NOW()`, `COUNT(*)`, `TRUE`,
@@ -595,7 +825,7 @@ All notable changes to AgentFlow are documented in this file.
595
825
  against the system trust store explicitly via
596
826
  `ssl.create_default_context()` plumbed through to `urlopen`. Insecure
597
827
  HTTP backends (default for local-compose) omit the context kwarg so
598
- Python's `http.client` path is unchanged. Closes part of Kimi audit
828
+ Python's `http.client` path is unchanged. Closes part of audit
599
829
  H-C2 (no explicit HTTPS validation). Two regression tests cover the
600
830
  secure (CERT_REQUIRED + check_hostname True) and insecure (`None`
601
831
  context) paths.
@@ -614,7 +844,7 @@ All notable changes to AgentFlow are documented in this file.
614
844
  rather than a 500. The latter parses its input through `sqlglot`
615
845
  (DuckDB dialect) and rejects multi-statement or non-`SELECT`
616
846
  payloads with `BackendExecutionError` before the `EXPLAIN` wrapper
617
- runs. Closes Kimi audit H-C1. 13 new regression tests in
847
+ runs. Closes audit H-C1. 13 new regression tests in
618
848
  `tests/unit/test_duckdb_backend_sql_hardening.py` pin both paths
619
849
  against an injection corpus (semicolons, comments, UNION,
620
850
  numeric-prefix names, dot-pathology, whitespace) plus
@@ -625,7 +855,7 @@ All notable changes to AgentFlow are documented in this file.
625
855
  prior hard-coded `223345` would collide on the replication stream the
626
856
  moment a second instance came up against the same source. Default
627
857
  preserved as `DEFAULT_MYSQL_SERVER_ID = 223345` so existing
628
- deployments are unchanged. Closes Kimi audit L-C2. Regression test
858
+ deployments are unchanged. Closes audit L-C2. Regression test
629
859
  `test_mysql_server_id_overridable_via_env` covers env override,
630
860
  invalid-int fallback, and unset-env fallback.
631
861
  - `_CONNECT_SECRET_KEY` in `src/ingestion/connectors/{mysql,postgres}_cdc.py`
@@ -634,13 +864,13 @@ All notable changes to AgentFlow are documented in this file.
634
864
  `FileConfigProvider` `${file:/path:<key>}` syntax, not a credential).
635
865
  The previous `"pass" + "word"` concatenation was security through
636
866
  obscurity — bytecode collapses the expression and string scanners
637
- still see the result. Closes Kimi audit L-C1.
867
+ still see the result. Closes audit L-C1.
638
868
  - Redundant `event_type == prefix` clauses dropped from
639
869
  `src/quality/validators/{schema,semantic}_validator.py`. Python's
640
870
  `str.startswith(prefix)` already returns True for the exact-equality
641
871
  case (`"order.".startswith("order.")`), so the `or event_type == prefix`
642
872
  branch could never fire when the prefix was a non-empty string.
643
- Closes Kimi audit L-C3.
873
+ Closes audit L-C3.
644
874
  - `AuthManager` no longer grows its `_rate_windows`,
645
875
  `_failed_auth_windows`, and `_runtime_plaintext_by_hash` dictionaries
646
876
  unbounded. A new `_sweep_expired_windows()` helper drops entries
@@ -650,7 +880,7 @@ All notable changes to AgentFlow are documented in this file.
650
880
  is cheap and bounds growth between reloads). `load()` also purges
651
881
  cached plaintext-by-hash entries for hashes that no longer appear in
652
882
  the live `_hashed_keys` list, so a revoked/rotated key's plaintext
653
- cannot remain pinned in memory across reloads. Closes Kimi audit
883
+ cannot remain pinned in memory across reloads. Closes audit
654
884
  H-C4. Regression tests in
655
885
  `tests/unit/test_auth_manager_memory_bounds.py` cover the sweep on
656
886
  load, the sweep on clear, the plaintext cache purge, and idempotency
@@ -664,15 +894,9 @@ wave 2 dependency bumps that landed in sessions 11–19.
664
894
 
665
895
  ### Documentation
666
896
 
667
- - Top-level [`docs/SESSION_HANDOFF.md`](docs/SESSION_HANDOFF.md) the
668
- entry point for picking up the project cold. Includes the four
669
- orientation commands to run first, the priority-tiered open work
670
- (Tier A actionable Dependabot PRs, Tier B externally user-gated
671
- A04/A05/A03, Tier C forward backlog), a compressed view of sessions
672
- 11 → 17, and the load-bearing lessons from session 17's regression
673
- (Contract Tests path filter, Dependabot cascade transitive
674
- conflicts, memory-staleness check before recommending). README
675
- surfaces it at the top of the Documentation index.
897
+ - Curated the README Documentation index as the cold-start entry point,
898
+ grouping the architecture, API reference, on-call runbooks, and security
899
+ audit so the project's published docs are reachable in one hop.
676
900
 
677
901
  ### Fixed
678
902
 
@@ -793,7 +1017,7 @@ wave 2 dependency bumps that landed in sessions 11–19.
793
1017
  optional-pyyaml `try/except ImportError` blocks (PyYAML is currently
794
1018
  a hard runtime dependency, but the JSON-fallback machinery in
795
1019
  `webhook_dispatcher.py`, `slo.py`, `alerts/dispatcher.py` etc. is
796
- intentionally kept available — see SESSION_HANDOFF.md anti-tasks).
1020
+ intentionally kept available).
797
1021
  - `types-redis` added to the dev extra. Two
798
1022
  `# type: ignore[import-untyped,unused-ignore]` annotations on
799
1023
  `import redis.asyncio as redis` retired in `src/serving/cache.py`
@@ -913,16 +1137,12 @@ wave 2 dependency bumps that landed in sessions 11–19.
913
1137
  - Prepared npm publishing for Trusted Publishing through GitHub Actions OIDC:
914
1138
  the TypeScript SDK publish workflow now requires npm CLI 11.5.1+ and no
915
1139
  longer passes `NPM_TOKEN` to the production `npm publish` step.
916
- - Recorded the npm Trusted Publishing handoff: the new package was first
917
- published as `@yuliaedomskikh/agentflow-client@1.1.0`, Trusted Publisher
918
- setup succeeded for `brownjuly2003-code/agentflow` with workflow
919
- `publish-npm.yml`, CLI `npm trust list` readback is complete, and future
920
- recovery-code use must keep a two-code reserve through the
921
- `npm-recovery-codes` skill.
922
- - Documented the completed replacement npm account bootstrap for
923
- `yulia.edomskikh@gmail.com`, the saved 2FA recovery-code reserve, and the
924
- switch of future TypeScript SDK publishing to
925
- `@yuliaedomskikh/agentflow-client`.
1140
+ - Recorded the npm Trusted Publishing handoff: the package
1141
+ `@yuliaedomskikh/agentflow-client@1.1.0` was first published and Trusted
1142
+ Publisher setup succeeded for `brownjuly2003-code/agentflow` with workflow
1143
+ `publish-npm.yml`; CLI `npm trust list` readback is complete.
1144
+ - Switched future TypeScript SDK publishing to the
1145
+ `@yuliaedomskikh/agentflow-client` npm scope.
926
1146
  - Clarified that legacy `NPM_TOKEN` revocation remains blocked until a
927
1147
  successful trusted-publish workflow run for `@yuliaedomskikh/agentflow-client`
928
1148
  and accepted external-gate intake evidence exist.
@@ -946,11 +1166,10 @@ wave 2 dependency bumps that landed in sessions 11–19.
946
1166
 
947
1167
  ### Security (audit follow-up sprint 2026-04-27/28)
948
1168
 
949
- Two external audits delivered against `4a13d36` (Claude Opus + Codex p1–p9,
950
- archived under `docs/audits/2026-04-27/`). Six commits closed all
951
- P0/P1/P2 findings.
1169
+ Two internal security audits were delivered against `4a13d36`. Six commits
1170
+ closed all P0/P1/P2 findings.
952
1171
 
953
- **Tenant isolation across the control plane (Codex p1 R3/R5, p2_1 #1-3,
1172
+ **Tenant isolation across the control plane (audit p1 R3/R5, p2_1 #1-3,
954
1173
  p3 #4):** `pipeline_events` and `dead_letter_events` got a
955
1174
  `tenant_id VARCHAR DEFAULT 'default'` column with backwards-compatible
956
1175
  `ALTER TABLE ADD COLUMN IF NOT EXISTS` migration in init paths. Writers
@@ -962,23 +1181,23 @@ normalizer accepts an explicit `topic=` argument and falls back through
962
1181
  now scope to `request.state.tenant_id`. Cross-tenant regression tests
963
1182
  added.
964
1183
 
965
- **SQL guard centralization (Codex p2_1 #4, p2_2 #4, p3 #1):** new
1184
+ **SQL guard centralization (audit p2_1 #4, p2_2 #4, p3 #1):** new
966
1185
  `_prepare_nl_sql()` helper in `nl_queries.py` is the only path that
967
1186
  validates translated SQL via `validate_nl_sql()`; called from
968
1187
  `execute_nl_query`, `paginated_query`, and `explain` before tenant
969
1188
  scoping and pagination wrapping. Closes the bypass on `/v1/query`
970
1189
  (paginated) and `/v1/query/explain`. PII masking and explain
971
1190
  `tables_accessed` rewritten on `sqlglot` AST so tenant-quoted SQL like
972
- `"acme"."users_enriched"` is correctly extracted (Codex p3 #3).
1191
+ `"acme"."users_enriched"` is correctly extracted (audit p3 #3).
973
1192
 
974
- **Entity allowlist enforcement (Codex p2_1 #4, p3 #2):** new
1193
+ **Entity allowlist enforcement (audit p2_1 #4, p3 #2):** new
975
1194
  `tenant_key_allowed_tables()` helper in `auth/manager.py`. Applied to
976
1195
  NL query / explain / paginated query, batch query/metric items,
977
1196
  `/v1/search` (intersection with tenant key allowlist + post-filter so
978
1197
  metric documents are not silently dropped for scoped keys), and
979
1198
  `/v1/metrics/{metric}`.
980
1199
 
981
- **Auth fail-closed + entropy + scopes (Codex p2_1 #5, p2_2 #1-3):**
1200
+ **Auth fail-closed + entropy + scopes (audit p2_1 #5, p2_2 #1-3):**
982
1201
  auth middleware now fails closed with `503` when no API keys are
983
1202
  configured; opt out with `AGENTFLOW_AUTH_DISABLED=true` for local dev
984
1203
  or `app.state.auth_disabled = True` for tests. Failed-auth throttling
@@ -987,7 +1206,7 @@ immediate peer is in `AGENTFLOW_TRUSTED_PROXIES`. Generated API keys
987
1206
  now use `secrets.token_urlsafe(32)` (256-bit) instead of
988
1207
  `secrets.token_hex(4)` (32-bit).
989
1208
 
990
- **Secret hygiene (Codex p2_2 #5/8, p9 #4-5):** rotated active webhook
1209
+ **Secret hygiene (audit p2_2 #5/8, p9 #4-5):** rotated active webhook
991
1210
  signing secret in `config/webhooks.yaml`, replaced tracked plaintext
992
1211
  API keys in `k8s/staging/values-staging.yaml` with placeholders +
993
1212
  `.yaml.example` schema reference, env-driven
@@ -1013,7 +1232,7 @@ capabilities, and applies `RuntimeDefault` seccomp; a memory `emptyDir`
1013
1232
  mounts at `/tmp` for Python tempfile / httpx caches. NetworkPolicy is
1014
1233
  off by default (enable per cluster).
1015
1234
 
1016
- **Supply chain (Codex p9):** committed `sdk-ts/package-lock.json`
1235
+ **Supply chain (audit p9):** committed `sdk-ts/package-lock.json`
1017
1236
  (closes ENOLOCK on `npm audit`); `publish-npm.yml` switched to
1018
1237
  `npm ci` + `npm test` + `npm audit` before publish. New `npm-audit` job
1019
1238
  added to `security.yml`. `aquasecurity/trivy-action` pinned from
@@ -1030,7 +1249,7 @@ SQL injection via dynamic partition keys), `langchain-core>=1.2.22`
1030
1249
  bypass), `langsmith>=0.7.31`. Both `pyproject.toml` and
1031
1250
  `integrations/pyproject.toml`.
1032
1251
 
1033
- **OpenAPI drift gate (Codex p4 #5):** `scripts/export_openapi.py`
1252
+ **OpenAPI drift gate (audit p4 #5):** `scripts/export_openapi.py`
1034
1253
  gained a `--check` mode that diffs the regenerated `docs/openapi.json`
1035
1254
  and `docs/agent-tools/*.json` against committed copies. Wired into
1036
1255
  `contract.yml`; `docs/agent-tools/**` and `scripts/export_openapi.py`
@@ -1047,7 +1266,7 @@ branch gate; the job was removed
1047
1266
  and DORA metrics fall back to the GitHub Actions API source
1048
1267
  already wired into `scripts/dora_metrics.py`.
1049
1268
 
1050
- **Python SDK alignment with server v1 contract (Codex p8 F1–F10):**
1269
+ **Python SDK alignment with server v1 contract (audit p8 F1–F10):**
1051
1270
  `api_version=` parameter and `X-AgentFlow-Version` header on sync and
1052
1271
  async clients; capture of server version + deprecation headers into
1053
1272
  `client.last_server_version` / `last_deprecation_warning`. Async
@@ -1069,7 +1288,7 @@ re-exported from `agentflow.__init__.__all__`. New
1069
1288
  `sdk/agentflow/py.typed` marker; Hatch include rule keeps it in the
1070
1289
  wheel/sdist.
1071
1290
 
1072
- **Test coverage gaps (Codex p5):** new unit suites covering
1291
+ **Test coverage gaps (audit p5):** new unit suites covering
1073
1292
  previously zero-coverage modules — `tests/unit/test_clickhouse_backend.py`
1074
1293
  (14 tests: SQL translation, basic-auth POST, UNKNOWN_TABLE mapping,
1075
1294
  URLError mapping, table_columns fallbacks, EXPLAIN, scalar, https
@@ -1087,9 +1306,9 @@ not exercise auth (sets `AGENTFLOW_AUTH_DISABLED=true`); opt out with
1087
1306
  the new `requires_auth_enforcement` marker.
1088
1307
  `app.state.auth_disabled = False` is reset on every lifespan startup
1089
1308
  so the test bypass flag does not leak across `TestClient` instances
1090
- (closes Codex review P2 on auth/middleware persistence).
1309
+ (closes review P2 on auth/middleware persistence).
1091
1310
 
1092
- **Documentation hygiene (Codex p6):** TypeScript SDK examples now
1311
+ **Documentation hygiene (audit p6):** TypeScript SDK examples now
1093
1312
  import from `"@yuliaedomskikh/agentflow-client"` (was `"agentflow"`); placeholder
1094
1313
  `https://api.agentflow.dev` examples replaced with
1095
1314
  `http://localhost:8000`; clone URL points at
@@ -1109,9 +1328,8 @@ reset on lifespan startup so the test bypass flag does not leak across
1109
1328
  `670 passed, 4 skipped` on
1110
1329
  `pytest tests/unit tests/integration tests/sdk tests/contract`.
1111
1330
 
1112
- **Audits archived:** the two source audits and the two CX task specs
1113
- that drove the impl are kept under `docs/audits/2026-04-27/` with a
1114
- README that maps findings to the six closing commits.
1331
+ **Audit closure:** two internal security audits drove the work; their
1332
+ findings map to the six closing commits.
1115
1333
 
1116
1334
  ### Added
1117
1335
 
@@ -1248,8 +1466,6 @@ See [docs/migration/v1.1.md](docs/migration/v1.1.md) for upgrade instructions fr
1248
1466
 
1249
1467
  ### Documentation
1250
1468
 
1251
- - v1.1 sprint task briefs under `docs/codex-tasks/2026-04-22/`
1252
- (T01-T10, self-contained one-PR ТЗ). (f448626)
1253
1469
  - `docs/operations/aws-oidc-setup.md`, `docs/operations/chaos-runbook.md`,
1254
1470
  `docs/operations/codecov-setup.md`.
1255
1471
  - `docs/contracts/how-to-add-entity.md`.