feat(auditlog): site script-side emitters stamp ParentExecutionId

This commit is contained in:
Joseph Doherty
2026-05-21 17:45:55 -04:00
parent 6af2607a50
commit 150ba5e63f
9 changed files with 343 additions and 60 deletions

View File

@@ -38,12 +38,22 @@ internal sealed class AuditingDbCommand : DbCommand
private readonly string _instanceName;
private readonly string? _sourceScript;
private readonly Guid _executionId;
/// <summary>
/// Audit Log #23 (ParentExecutionId): the spawning execution's id when this
/// run was inbound-API-routed; <c>null</c> for non-routed runs. Threaded
/// alongside <see cref="_executionId"/> and stamped onto the <c>DbWrite</c>
/// audit row.
/// </summary>
private readonly Guid? _parentExecutionId;
private readonly ILogger _logger;
private DbConnection? _wrappingConnection;
// Parameter ordering: executionId sits immediately after the ILogger,
// consistent with the other three audit-threaded ctors (ExternalSystemHelper,
// DatabaseHelper, AuditingDbConnection).
// DatabaseHelper, AuditingDbConnection). parentExecutionId is a trailing
// optional param so existing positional callers stay source-compatible.
public AuditingDbCommand(
DbCommand inner,
IAuditWriter auditWriter,
@@ -52,7 +62,8 @@ internal sealed class AuditingDbCommand : DbCommand
string instanceName,
string? sourceScript,
ILogger logger,
Guid executionId)
Guid executionId,
Guid? parentExecutionId = null)
{
_inner = inner ?? throw new ArgumentNullException(nameof(inner));
_auditWriter = auditWriter ?? throw new ArgumentNullException(nameof(auditWriter));
@@ -62,6 +73,7 @@ internal sealed class AuditingDbCommand : DbCommand
_sourceScript = sourceScript;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_executionId = executionId;
_parentExecutionId = parentExecutionId;
}
// -- Forwarded surface ------------------------------------------------
@@ -438,6 +450,9 @@ internal sealed class AuditingDbCommand : DbCommand
// trust-boundary rows from the same script run.
CorrelationId = null,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning execution's id;
// null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,

View File

@@ -37,11 +37,21 @@ internal sealed class AuditingDbConnection : DbConnection
private readonly string _instanceName;
private readonly string? _sourceScript;
private readonly Guid _executionId;
/// <summary>
/// Audit Log #23 (ParentExecutionId): the spawning execution's id when this
/// run was inbound-API-routed; <c>null</c> for non-routed runs. Threaded
/// alongside <see cref="_executionId"/> into the
/// <see cref="AuditingDbCommand"/> so its <c>DbWrite</c> row stamps it.
/// </summary>
private readonly Guid? _parentExecutionId;
private readonly ILogger _logger;
// Parameter ordering: executionId sits immediately after the ILogger,
// consistent with the other three audit-threaded ctors (ExternalSystemHelper,
// DatabaseHelper, AuditingDbCommand).
// DatabaseHelper, AuditingDbCommand). parentExecutionId is a trailing
// optional param so existing positional callers stay source-compatible.
public AuditingDbConnection(
DbConnection inner,
IAuditWriter auditWriter,
@@ -50,7 +60,8 @@ internal sealed class AuditingDbConnection : DbConnection
string instanceName,
string? sourceScript,
ILogger logger,
Guid executionId)
Guid executionId,
Guid? parentExecutionId = null)
{
_inner = inner ?? throw new ArgumentNullException(nameof(inner));
_auditWriter = auditWriter ?? throw new ArgumentNullException(nameof(auditWriter));
@@ -60,6 +71,7 @@ internal sealed class AuditingDbConnection : DbConnection
_sourceScript = sourceScript;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_executionId = executionId;
_parentExecutionId = parentExecutionId;
}
// ConnectionString is settable on DbConnection — forward both halves.
@@ -99,7 +111,10 @@ internal sealed class AuditingDbConnection : DbConnection
_instanceName,
_sourceScript,
_logger,
_executionId);
_executionId,
// Audit Log #23 (ParentExecutionId): the spawning execution's id,
// threaded alongside _executionId. Null for non-routed runs.
_parentExecutionId);
}
protected override void Dispose(bool disposing)

View File

@@ -626,6 +626,9 @@ public class ScriptRuntimeContext
// per-execution id shared across this script run.
CorrelationId = trackedId.Value,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning
// execution's id; null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,
@@ -739,6 +742,9 @@ public class ScriptRuntimeContext
// ExecutionId = per-execution id for this script run.
CorrelationId = trackedId.Value,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning
// execution's id; null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,
@@ -803,6 +809,9 @@ public class ScriptRuntimeContext
// ExecutionId = per-execution id for this script run.
CorrelationId = trackedId.Value,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning
// execution's id; null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,
@@ -980,6 +989,9 @@ public class ScriptRuntimeContext
// one script run can be correlated together.
CorrelationId = null,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning execution's
// id; null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,
@@ -1127,7 +1139,10 @@ public class ScriptRuntimeContext
instanceName: _instanceName,
sourceScript: _sourceScript,
logger: _logger,
executionId: _executionId);
executionId: _executionId,
// Audit Log #23 (ParentExecutionId): the spawning execution's
// id, threaded alongside _executionId. Null for non-routed runs.
parentExecutionId: _parentExecutionId);
}
/// <summary>
@@ -1203,6 +1218,9 @@ public class ScriptRuntimeContext
// (TrackedOperationId); ExecutionId = per-execution id.
CorrelationId = trackedId.Value,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning
// execution's id; null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,
@@ -1571,6 +1589,9 @@ public class ScriptRuntimeContext
// lifecycle id; ExecutionId carries the per-execution id.
CorrelationId = correlationId,
ExecutionId = _executionId,
// Audit Log #23 (ParentExecutionId): the spawning
// execution's id; null for non-routed runs.
ParentExecutionId = _parentExecutionId,
SourceSiteId = string.IsNullOrEmpty(_siteId) ? null : _siteId,
SourceInstanceId = _instanceName,
SourceScript = _sourceScript,