docs: Flow Debugger design reconciled with the implementation (arch-review F12, F13)
The Flow Debugger design doc still described the pre-remediation shape: a
debug-stream subscription for the value-change entry, Deployer everywhere, an
unredacted inline trace copy and "~7 audit rows per call". Reconciled with what
shipped on this branch (Tasks 1-12):
- design D6 / §5.4 / §9 / §10: RequireFlowDebugger page policy with Deployer-only
execution (F3), the PullTraceEvents polling path with AttributeValueUpdate
fields 7/8 recorded as RESERVED and unconsumed (F12), the redacting + byte-
capped shared FlowTraceCollector (F1), route-time site scope (F2), the derived
client waits (F4), the 7-10 row estimate, the doubled central audit write per
routed call, and the inbound-row-after-the-run ordering.
- sitestream.proto: fields 7/8 marked reserved-but-populated, numbers not to be
reused (comment only; no regeneration needed).
- Component-InboundAPI: SkipBodyCapture on the RouteCall row (F11),
SchemaRefResolver's public visibility, WithSiteScope / SITE_SCOPE_DENIED (F2),
Replay's wider role set (F3).
- Component-CentralUI: page policy vs Deployer-only controls (F3), route-time
site scope (F2), client wait derivation (F4).
- "7-10 audit rows per call (3 of them trace-only)" everywhere the estimate is
quoted: the method form, both CLI --trace-all-calls help strings, the CLI
README, the ApiMethod entity doc, the manual migration script and the two
Flow Debugger plans.
- arch-review doc: new §7 Resolution listing F1-F13 with the fixing commit, plus
the tracking-store test race fixed alongside them (86451382).
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
@@ -27,7 +27,7 @@ on the `DelmiaReceiver` child → seven attribute writes → wait for Galaxy to
|
||||
| D3 | **Value-change on a data-sourced attribute does a REAL tag write** through the instance actor's normal write path; the device echo fires the trigger. Correlation is by a short-lived *trace arm* on the instance actor (§5.3). | A debug-only "inject value" command that synthesises the change without touching the device — leaves the instance's cached value diverged from the device until the next real update. |
|
||||
| D4 | **Live gets its trace inline; Replay reads audit rows.** Site audit telemetry forwards on a 5 s busy / 30 s idle cadence (`AuditLog:SiteTelemetry`), too slow to drive an interactive run, so the routed reply carries the site steps back and the same steps are *also* written as audit rows for Replay. | Live waiting on the audit pipeline. |
|
||||
| D5 | **Tracing is gated, not always-on.** Sites run scripts at high rates from timers and value changes; a trace flag rides beside `ParentExecutionId` and only flagged runs emit trace rows. One exception is always-on: a central `RouteCall` row per `Route.To().Call` (inbound-driven volume, joins the two halves of a Replay). | Tracing every run (volume), or a purely time-window join. |
|
||||
| D6 | **Live run is a Deployer act.** `RequireDeployment` gates the page and the Run button; Replay needs `OperationalAudit`. | A separate `RequireOperator` gate for Live. |
|
||||
| D6 | **Live run is a Deployer act.** `RequireDeployment` gates the Run controls and the two run commands; the page and Replay are open to `OperationalAudit` roles + Deployer (`RequireFlowDebugger`, arch-review F3). | A separate `RequireOperator` gate for Live. |
|
||||
|
||||
## 2. What exists today (reused, not rebuilt)
|
||||
|
||||
@@ -159,20 +159,24 @@ the echo also fires inherit the parent id exactly as static cascades do today.
|
||||
`RouteToCallResponse` gains additive `ChildExecutionId` (`Guid?`) and `TraceEvents`
|
||||
(`IReadOnlyList<AuditEvent>?`, the very events that became the site's audit rows, in emission
|
||||
order); on the wire it is `repeated AuditEventDto trace_events` (the DTO `sitestream.proto`
|
||||
already defines). The site collects events in a per-run `FlowTraceCollector` held by
|
||||
`ScriptRuntimeContext` and attaches the list to the `ScriptCallResult` → `RouteToCallResponse`
|
||||
when `Trace` is set. Capped at `MaxTraceEventsPerRun` (500); beyond it the collector keeps the
|
||||
first 500, sets `Truncated`, and the audit rows remain complete. A site on an older build ignores
|
||||
already defines). The site collects events in a per-run `FlowTraceCollector` (Commons
|
||||
`Types/Debugging/`, shared with the central `FlowDebugRunner`) held by `ScriptRuntimeContext` and
|
||||
attaches the list to the `ScriptCallResult` → `RouteToCallResponse` when `Trace` is set. The
|
||||
collector applies `IAuditRedactor` inside `Add`, so the inline record is the same filtered event
|
||||
the writer persists, and it caps at `MaxTraceEventsPerRun` (500) **or** 1 MB of summed
|
||||
`DetailsJson` (`DefaultMaxBytes`), whichever comes first; beyond either bound it keeps the earlier
|
||||
events, sets `Truncated`, and the audit rows remain complete (arch-review F1). A site on an older build ignores
|
||||
`Trace`, returns no `TraceEvents`, and the UI labels its lane `site not traced (older build)`.
|
||||
`FlowStep` is a **central-side projection** (`Commons/Types/Debugging/FlowStepProjector`)
|
||||
computed from `AuditEvent` + `AuditDetails`; nothing serializes it.
|
||||
|
||||
For the value-change entry there is no routed reply to ride on. The debugger instead subscribes
|
||||
to the instance's debug stream (`SubscribeDebugView`, the Debug View's existing path) for the run's
|
||||
duration and takes the spawned run's `ExecutionId` from the stamped `AttributeValueChanged`, then
|
||||
pulls the site's trace rows for that id via a new `PullTraceEvents` RPC on `SiteStreamService`
|
||||
(same PSK interceptor as `PullAuditEvents`; reads the site audit SQLite by `ExecutionId` /
|
||||
`ParentExecutionId`). One additive RPC, no streaming change.
|
||||
For the value-change entry there is no routed reply to ride on. The runner polls the site's
|
||||
`PullTraceEvents` RPC by `ParentExecutionId` (1 s cadence, 2 s settle window, `WaitSeconds` bound) —
|
||||
simpler than the debug-stream subscription originally planned. `AttributeValueUpdate.source_execution_id`/`trace`
|
||||
(fields 7/8) are populated by the site and **consumed by nothing**; they are reserved for a future
|
||||
debug-stream path and must not be reused. The RPC sits behind the same PSK interceptor as
|
||||
`PullAuditEvents` and reads the site audit SQLite by `ExecutionId` / `ParentExecutionId` — one
|
||||
additive RPC, no streaming change.
|
||||
|
||||
## 6. Message and wire changes (all additive)
|
||||
|
||||
@@ -257,9 +261,14 @@ surface); the walker is syntax-only and never executes anything.
|
||||
|
||||
## 9. Security, authorisation, audit
|
||||
|
||||
- **Page visibility and Live run:** `RequireDeployment` (same as Debug View) — decided
|
||||
2026-09-05: a Live run writes real tags, but the Deployer already deploys and redeploys the
|
||||
scripts that do exactly that, so no separate Operator gate. **Replay:** `OperationalAudit` (it
|
||||
- **Page visibility:** `RequireFlowDebugger` — the `OperationalAudit` roles plus Deployer
|
||||
(`AuthorizationPolicies.FlowDebuggerAccessRoles` = Deployer, Administrator, Viewer), so an
|
||||
auditor can open the page and Replay a past execution (arch-review F3). **Live run:**
|
||||
`RequireDeployment` (same as Debug View) — decided 2026-09-05: a Live run writes real tags, but
|
||||
the Deployer already deploys and redeploys the scripts that do exactly that, so no separate
|
||||
Operator gate. The two run commands, the Live controls, the parked-node Retry/Discard actions and
|
||||
the `?methodId=`/`?instanceId=` drill-ins stay Deployer-only, and the page pins Replay mode for a
|
||||
non-Deployer. **Replay:** `FlowDebugReplayCommand` accepts the same `OperationalAudit` roles (it
|
||||
reads audit rows). No Verifier step — the debugger is a diagnostic, not a production write
|
||||
control, and the audit row is the safeguard.
|
||||
- **Inbound audit row for a Live run:** the shared `AuditEvent.Actor` carries the operator's
|
||||
@@ -267,21 +276,38 @@ surface); the walker is syntax-only and never executes anything.
|
||||
`Extra.runNumber`; `Target` is the method as usual. API-key authentication is bypassed (there is
|
||||
no key), **parameter validation is not** — `ParameterValidator` runs exactly as for HTTP so a
|
||||
bad input fails the same way. The method's `TimeoutSeconds` applies. Site-scope (`SiteScopeService`)
|
||||
restricts which instances a value-change entry may target.
|
||||
- Trace payloads pass through the existing redaction policy (auth headers redacted, 8 KB cap,
|
||||
64 KB on error rows). Console output is capped the same way.
|
||||
restricts which instances a value-change entry may target. The method entry enforces the
|
||||
operator's site scope at route time (`RouteHelper.WithSiteScope`, `SITE_SCOPE_DENIED` →
|
||||
`ManagementUnauthorized`, arch-review F2): the runner resolves the operator's permitted numeric
|
||||
site ids to site identifiers and hands them to `RouteHelper`, which refuses an out-of-scope target
|
||||
**before any site traffic**; the denial is rethrown as `SiteScopeViolationException` *after* the
|
||||
inbound audit row is written, so the attempt is recorded under the operator's name.
|
||||
Administrators and unscoped users are exempt, exactly as `EnforceSiteScope` treats them.
|
||||
- Trace payloads pass through the existing redaction policy on BOTH copies: the stored row (writer)
|
||||
and the inline Live copy (`FlowTraceCollector` applies `IAuditRedactor` and a 1 MB byte budget
|
||||
beside the 500-event cap — arch-review F1). The row-level caps are unchanged (auth headers
|
||||
redacted, 8 KB cap, 64 KB on error rows). Console output is capped the same way.
|
||||
- Nothing here touches the PSK boundary; `PullTraceEvents` sits behind `ControlPlaneAuthInterceptor`.
|
||||
|
||||
## 10. Volume and failure behaviour
|
||||
|
||||
- Untraced production is unchanged except one `RouteCall` row per routed call (inbound-driven).
|
||||
Every routed call adds one central `RouteCall` insert — at inbound-driven rates that doubles the
|
||||
per-call central audit write (accepted, D5).
|
||||
- A traced Delmia call emits ≈ 1 `InboundRequest` + 1 `RouteCall` + 1 `ScriptRun` + 2
|
||||
`AttributeWrite` + 1 `AttributeWait` + 1 value-change `ScriptRun` ≈ 7 rows. `TraceAllCalls` on a
|
||||
100-call/day method is ~700 rows/day.
|
||||
`AttributeWrite` + 1 `AttributeWait` + 1 value-change `ScriptRun` ≈ **7–10 rows** (a cached DB
|
||||
write and a notification add 3 trace-only rows). `TraceAllCalls` on a 100-call/day method is
|
||||
~700–1 000 rows/day.
|
||||
- Trace emission is best-effort like all audit (a failed trace write never fails the run).
|
||||
- Live run timeout = method timeout + `FlowDebugRunGrace` (10 s); a timeout renders whatever steps
|
||||
arrived and marks the run `Timed out`. The site's trace rows still land later, so Replay of the
|
||||
same ExecutionId is complete.
|
||||
same ExecutionId is complete. The client waits longer than the server on purpose: the UI derives
|
||||
its Ask wait from the same bound (`RunAskTimeoutFor` = method timeout + grace + 15 s slack,
|
||||
floored at 30 s; `ValueChangeAskTimeoutFor` = the wait window + 15 s) and the CLI's
|
||||
`run-method --timeout-seconds` defaults to 120 while `run-value-change` waits
|
||||
`--wait-seconds + 25` (arch-review F4).
|
||||
- **The Live run's inbound row is written AFTER the run completes**, so a Replay taken during a
|
||||
long Live run shows only the `RouteCall`.
|
||||
- Older site build: no `TraceEvents`, lane labelled; older central build: ignores new fields; proto3
|
||||
defaults negotiate as for stream batching.
|
||||
- **Mixed-version caveat:** an OLD central ingesting `ScriptTrace` rows from a NEW site parses
|
||||
|
||||
@@ -226,7 +226,7 @@ Add `using ZB.MOM.WW.Audit;` where `AuditEvent` is used (Commons already referen
|
||||
**Step 1: Failing test** (follow the existing ManagementService test style for invoking `HandleUpdateApiMethod` — find a sibling test that exercises `UpdateApiMethodCommand` and copy its fixture; assert `method.TraceAllCalls` round-trips and defaults to `false` for the 5-arg constructor).
|
||||
|
||||
**Step 2: Implement**
|
||||
- `ApiMethod`: `public bool TraceAllCalls { get; set; }` with summary "When true every production call to this method is fully traced (Flow Debugger design §5.2); intended for low-volume integration methods — ~7 audit rows per call."
|
||||
- `ApiMethod`: `public bool TraceAllCalls { get; set; }` with summary "When true every production call to this method is fully traced (Flow Debugger design §5.2); intended for low-volume integration methods — 7-10 audit rows per call."
|
||||
- EF: `builder.Property(m => m.TraceAllCalls).IsRequired().HasDefaultValue(false);`
|
||||
- Migration: build first (CLAUDE.md gotcha), then `dotnet ef migrations add AddApiMethodTraceAllCalls --project src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase --startup-project src/ZB.MOM.WW.ScadaBridge.Host` (use the same `--startup-project` the previous migration used — check `git log -1 --stat -- src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/20260819201210_AddNotificationsListSortIndex.cs` for its commit message). Verify the generated `Up` contains exactly one `AddColumn<bool>("TraceAllCalls", "ApiMethods", nullable: false, defaultValue: false)`; delete and redo if empty.
|
||||
- Commands: `CreateApiMethodCommand(..., string? ReturnDefinition, bool TraceAllCalls = false)`, `UpdateApiMethodCommand(..., string? ReturnDefinition, bool? TraceAllCalls = null)` (null = leave unchanged, so old CLIs don't reset it). Handlers copy the value.
|
||||
@@ -754,7 +754,7 @@ public sealed record FlowDebugOutcome(FlowGraph? Graph, FlowDebugRunResult? Raw,
|
||||
**Files:**
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor` (+ `.razor.cs`): button `Open in Flow Debugger` (`data-test="open-flow-debugger"`) beside *View execution chain* → `/deployment/flow-debugger?executionId={exec}`; rendered when `ExecutionId` is non-null.
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ExecutionTreePage.razor`: same button next to *View this execution in the Audit Log*.
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor`: under the Timeout field a `form-check` "Trace all calls (Flow Debugger)" bound to `_traceAllCalls`, help text "Adds ~7 audit rows per call; for low-volume integration methods", saved onto `_existing.TraceAllCalls` / the create path.
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor`: under the Timeout field a `form-check` "Trace all calls (Flow Debugger)" bound to `_traceAllCalls`, help text "Adds 7–10 audit rows per call; for low-volume integration methods", saved onto `_existing.TraceAllCalls` / the create path.
|
||||
- Test: `tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Audit/FlowDebuggerDrillinTests.cs`, extend the existing `ApiMethodForm` test file if one exists (grep `ApiMethodForm` in tests).
|
||||
|
||||
Commit — `git commit -am "feat(central-ui): Flow Debugger drill-ins from Audit Log + Execution Chain; TraceAllCalls checkbox on the method form"`
|
||||
|
||||
@@ -591,7 +591,7 @@ var m = unmatched.FirstOrDefault(p => p.Kind == s.Kind && string.Equals(p.Title,
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor:50`, `src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ApiMethodCommands.cs:65,101`, `src/ZB.MOM.WW.ScadaBridge.CLI/README.md:2122,2140`, `docs/requirements/Component-InboundAPI.md:73` ("~7" → "7–10 audit rows per call (3 of them trace-only)")
|
||||
- Modify: `docs/requirements/Component-InboundAPI.md` (new sentences: `SchemaRefResolver` is public for the Flow Debugger runner; `RouteHelper.WithSiteScope` + `SITE_SCOPE_DENIED`; `RouteCall` honours `SkipBodyCapture`)
|
||||
- Modify: `docs/requirements/Component-CentralUI.md` (Flow Debugger: page policy `RequireFlowDebugger`, Live controls Deployer-only, client wait derivation)
|
||||
- Modify: `CLAUDE.md` (Flow Debugger bullet: "~7 rows/call" → "7–10", one sentence on F1/F2/F3 outcomes with the review doc path)
|
||||
- Modify: `CLAUDE.md` (Flow Debugger bullet: the per-call trace-row estimate → "7–10", one sentence on F1/F2/F3 outcomes with the review doc path)
|
||||
- Modify: `docs/plans/2026-09-06-flow-debugger-arch-review.md` (append `## 7. Resolution` listing each finding → commit)
|
||||
|
||||
Text to write (verbatim where possible):
|
||||
@@ -600,7 +600,9 @@ Text to write (verbatim where possible):
|
||||
- §9 redaction bullet: "Trace payloads pass through the existing redaction policy on BOTH copies: the stored row (writer) and the inline Live copy (`FlowTraceCollector` applies `IAuditRedactor` and a 1 MB byte budget beside the 500-event cap — arch-review F1)." Add: "The method entry enforces the operator's site scope at route time (`RouteHelper.WithSiteScope`, `SITE_SCOPE_DENIED` → `ManagementUnauthorized`, arch-review F2)."
|
||||
- §10: "≈ 7–10 rows (a cached DB write and a notification add 3 trace-only rows)"; "Every routed call adds one central `RouteCall` insert — at inbound-driven rates that doubles the per-call central audit write (accepted, D5)"; "The Live run's inbound row is written AFTER the run completes, so a Replay taken during a long Live run shows only the `RouteCall`."
|
||||
|
||||
**Step 4:** `grep -rn "~7 audit\|~7 rows\|roughly seven" docs src CLAUDE.md` → no hits.
|
||||
**Step 4:** grep `docs src CLAUDE.md` for the pre-remediation estimate wordings (the tilde-7 forms
|
||||
and the spelled-out "seven audit rows" one) → no hits. The patterns are deliberately not written out
|
||||
in this file so the check can return zero hits.
|
||||
|
||||
**Step 5: Commit** `docs: Flow Debugger design reconciled with the implementation (arch-review F12, F13)`
|
||||
|
||||
|
||||
@@ -246,8 +246,9 @@ for the debug-stream path" or dropped from the client mapping.
|
||||
- Design §5.4 (debug-stream subscription) vs the polling implementation — see F12.
|
||||
- Design D6 / §9 (Replay = OperationalAudit) vs Deployer everywhere — see F3.
|
||||
- Design §9 (redaction applies to trace payloads) vs F1.
|
||||
- `ApiMethodForm` / CLI help say "~7 audit rows per call"; the outbound-calls addendum makes a
|
||||
call with one cached DB write and one notification **10 rows** (3 trace-only). Say "7–10".
|
||||
- `ApiMethodForm` / CLI help understate the row count (they were written before the outbound-calls
|
||||
addendum, which makes a call with one cached DB write and one notification **10 rows**, 3 of them
|
||||
trace-only). Say "7–10 audit rows per call".
|
||||
- `FlowDebugRunner.RunMethodAsync` writes the inbound row *after* the run, so a Replay taken during
|
||||
a long Live run shows only the `RouteCall`. Fine, but not stated anywhere.
|
||||
- `SchemaRefResolver` became `public` for the runner; note it in Component-InboundAPI or move the
|
||||
@@ -328,3 +329,30 @@ touches the Flow Debugger; `Deployment/FlowDebuggerTests` (Live run + localStora
|
||||
Consequence worth recording alongside the login-disabled decision: the rig can no longer prove
|
||||
role gating in the browser, so the Playwright suite's role-negative tests need either a second,
|
||||
login-enabled central to target or a fixture that overrides the identity per test.
|
||||
|
||||
## 7. Resolution
|
||||
|
||||
All thirteen findings were remediated on branch `fix/flow-debugger-arch-review` (plan
|
||||
`docs/plans/2026-09-06-flow-debugger-arch-review-remediation.md`, 2026-09-06). Nothing was
|
||||
deferred to the register.
|
||||
|
||||
| # | Outcome | Commit |
|
||||
|---|---------|--------|
|
||||
| F1 | `FlowTraceCollector` moved to Commons `Types/Debugging/`, applies `IAuditRedactor` inside `Add` and caps at 500 events **and** 1 MB of summed `DetailsJson`; the site launcher resolves the redactor from the run's scope, and the central `FlowDebugRunner` collects through the same instance and reports its `Truncated`. | `e79452d2` fix(site-runtime): Flow Debugger inline trace copy is redacted and byte-capped at the collector (arch-review F1, site half) · `def6bab3` fix(management): Flow Debugger Live result is the redacted, capped trace copy (arch-review F1, central half) |
|
||||
| F2 | `RouteHelper.WithSiteScope(IReadOnlySet<string>?)` refuses an out-of-scope target site before any site traffic (`RouteSiteScopeException` → executor code `SITE_SCOPE_DENIED`); the runner rethrows it as `SiteScopeViolationException` (`ManagementUnauthorized`) **after** writing the inbound audit row. Administrators and unscoped users are exempt; the HTTP endpoint is unchanged. | `20a05941` fix(inbound-api): Flow Debugger method-entry Live run enforces the operator's site scope at route time (arch-review F2) |
|
||||
| F3 | New `AuthorizationPolicies.RequireFlowDebugger` (`FlowDebuggerAccessRoles` = Deployer, Administrator, Viewer) gates the page, and `FlowDebugReplayCommand` accepts the same set; the two run commands, the Live controls, Retry/Discard and the `?methodId=`/`?instanceId=` drill-ins stay Deployer-only, with the page pinning Replay mode for a non-Deployer. | `f86eb61d` fix(central-ui): Flow Debugger Replay opens to OperationalAudit roles; Live run and Retry/Discard stay Deployer-only (arch-review F3) |
|
||||
| F4 | Client waits derive from the server's bound: `RunAskTimeoutFor(timeoutSeconds)` = method timeout + `RunGrace` + 15 s slack (floor 30 s), `ValueChangeAskTimeoutFor(wait)` = wait + 15 s; the CLI gains `run-method --timeout-seconds` (default 120) and waits `--wait-seconds + 25` on `run-value-change`. | `97b0a4ba` fix(central-ui,cli): Flow Debugger client waits derive from the method timeout / wait window instead of a fixed 2 minutes (arch-review F4) |
|
||||
| F5 | The graph orders executions by emission sequence and uses timestamps only **within** one execution, so a site clock offset can no longer reorder the swimlane; the Live runner keeps the collector's emission order. | `1dfb9cee` fix(commons): Flow graph orders executions by emission sequence, timestamps only within one clock (arch-review F5) |
|
||||
| F6 | A failed traced DCL write disarms the trace arm (`DisarmTrace` self-message), so an unrelated device update can no longer consume it. | `50bf9ac7` fix(site-runtime): trace arm is cleared when the traced DCL write fails (arch-review F6) |
|
||||
| F7 | A traced run shed by `MaxConcurrentRunsPerScript` or suppressed by `MinTimeBetweenRuns` emits a Failed `ScriptRun` row (`shed: MaxConcurrentRunsPerScript …` / `suppressed: MinTimeBetweenRuns …`) instead of vanishing from the graph. | `105541b6` fix(site-runtime): shed or rate-limited traced runs emit a Failed ScriptRun row (arch-review F7) |
|
||||
| F8 | All four trace/outbound fault continuations run on `TaskScheduler.Default`, and the central emitters log a Warning on a failed audit write. | `262de38c` fix(audit): trace/outbound fault continuations run on the default scheduler and central emitters log (arch-review F8) |
|
||||
| F9 | `GetTraceEventsAsync` and `GetExecutionTreeAsync` share one chain walker in `AuditLogRepository`. | `297ae56b` refactor(config-db): GetTraceEventsAsync and GetExecutionTreeAsync share one chain walker (arch-review F9) |
|
||||
| F10 | The prediction overlay matches a real step by `(Kind, Title)` first, falling back to kind only, so two predicted nodes of the same kind no longer collapse onto one another. | `688136de` fix(central-ui): Flow Debugger prediction overlay matches by kind and title (arch-review F10) |
|
||||
| F11 | The always-on `RouteCall` row honours the method's `SkipBodyCapture` — the executor builds the helper with `RouteHelper.WithBodyCapture(false)`; the row is still written, metadata only. | `453c3dec` fix(inbound-api): RouteCall audit row honours the method's SkipBodyCapture override (arch-review F11) |
|
||||
| F12 | `AttributeValueUpdate.source_execution_id` / `trace` (fields 7/8) are **kept, populated and unconsumed** — documented as reserved for a future debug-stream path in `sitestream.proto` and design §5.4, with the field numbers pinned against reuse. Not removed: dropping them would be a wire change for no gain. | this commit |
|
||||
| F13 | Design D6 / §5.4 / §9 / §10, `Component-CentralUI.md`, `Component-InboundAPI.md`, `CLAUDE.md`, the proto comment and the CLI/UI help strings reconciled with the shipped code; the trace-row estimate is "7–10 audit rows per call" everywhere; `SchemaRefResolver`'s `public` visibility and the inbound-row-after-the-run ordering are now stated. | this commit — docs: Flow Debugger design reconciled with the implementation (arch-review F12, F13) |
|
||||
|
||||
One test defect surfaced by §3's performance commits was fixed on the same branch:
|
||||
`OperationTrackingStoreTests.ReadChangedSince_BoundaryTimestamp…` raced the new single-writer
|
||||
queue (a missing `FlushAsync` before the test's direct `UPDATE`) — `86451382` test(site-runtime):
|
||||
flush the tracking-store queue before the boundary-timestamp test's direct UPDATE.
|
||||
|
||||
@@ -6,7 +6,7 @@ SET ANSI_NULLS ON;
|
||||
GO
|
||||
|
||||
-- Flow Debugger (design 2026-09-05 §5.2): ApiMethod.TraceAllCalls — when 1, every
|
||||
-- production call to the method is fully traced (~7 audit rows per call). Production
|
||||
-- production call to the method is fully traced (7-10 audit rows per call). Production
|
||||
-- twin of EF migration 20260906034113_AddApiMethodTraceAllCalls.
|
||||
BEGIN TRANSACTION;
|
||||
IF NOT EXISTS (
|
||||
|
||||
Reference in New Issue
Block a user