feat(ui): drill-ins from detail pages to Audit Log (#23 M7)

Adds "Recent audit activity" deep links from four edit/detail pages into
the central Audit Log, each with a pre-filter encoded in the query string
that the Audit Log page (Bundle D0) now parses on initialization:

  - External Systems (Design/ExternalSystemForm)      → ?target={Name}
  - API Keys         (Admin/ApiKeyForm)                → ?actor={Name}&channel=ApiInbound
  - Sites            (Admin/SiteForm)                  → ?site={SiteIdentifier}
  - Instances        (Deployment/InstanceConfigure)    → ?instance={UniqueName}

The link is suppressed on create/new flows where there is nothing to
drill into yet. Instance is UI-only on the filter bar (the repository
filter contract has no instance column), so the page-side prefill threads
through the InitialInstanceSearch seam on AuditFilterBar.

Site Calls (#22 M7-T11) drill-in is DEFERRED: the Central UI does not
yet host a Site Calls listing page, per M3 reality notes. Add the
drill-in when that page lands.

#23 M7-T12
This commit is contained in:
Joseph Doherty
2026-05-20 20:26:28 -04:00
parent 1c20e81d77
commit 38fc9b4102
8 changed files with 366 additions and 2 deletions

View File

@@ -27,6 +27,17 @@
@:Add API Key
}
</h4>
@* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit Log
pre-filtered to this API key's inbound calls. Inbound audit rows record
the key Name as Actor and live on the ApiInbound channel. *@
@if (IsEditMode && !string.IsNullOrWhiteSpace(_formName))
{
<a class="btn btn-outline-secondary btn-sm ms-auto"
href="/audit/log?actor=@Uri.EscapeDataString(_formName)&channel=ApiInbound"
data-test="audit-link">
Recent audit activity
</a>
}
</div>
<ToastNotification @ref="_toast" />

View File

@@ -20,7 +20,20 @@
<div class="card mb-3">
<div class="card-body">
<h6 class="card-title">@(IsEditMode ? "Edit Site" : "Add Site")</h6>
<div class="d-flex justify-content-between align-items-start">
<h6 class="card-title">@(IsEditMode ? "Edit Site" : "Add Site")</h6>
@* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit
Log pre-filtered to this site's events. AuditEvent.SourceSiteId
stores the SiteIdentifier (string), so we pass that through. *@
@if (IsEditMode && !string.IsNullOrWhiteSpace(_formIdentifier))
{
<a class="btn btn-outline-secondary btn-sm"
href="/audit/log?site=@Uri.EscapeDataString(_formIdentifier)"
data-test="audit-link">
Recent audit activity
</a>
}
</div>
<div class="mb-2">
<label class="form-label small">Identifier</label>
<input type="text" class="form-control form-control-sm" @bind="_formIdentifier"

View File

@@ -22,6 +22,18 @@
<div class="d-flex align-items-center mb-3">
<button class="btn btn-outline-secondary btn-sm me-3" @onclick="GoBack">&larr; Back to Topology</button>
<h4 class="mb-0">Configure Instance</h4>
@* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit Log
pre-filtered to this instance. Instance is UI-only on the filter bar
(AuditEvent has no Instance column), so we use the ?instance= UI-text
seam — the filter bar's Instance free-text input is pre-populated. *@
@if (_instance != null)
{
<a class="btn btn-outline-secondary btn-sm ms-auto"
href="/audit/log?instance=@Uri.EscapeDataString(_instance.UniqueName)"
data-test="audit-link">
Recent audit activity
</a>
}
</div>
<ToastNotification @ref="_toast" />

View File

@@ -10,7 +10,20 @@
<div class="container-fluid mt-3">
<button class="btn btn-link text-decoration-none ps-0 mb-2" @onclick="GoBack">&larr; Back</button>
<h4 class="mb-3">@(Id.HasValue ? "Edit External System" : "Add External System")</h4>
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="mb-0">@(Id.HasValue ? "Edit External System" : "Add External System")</h4>
@* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit Log
pre-filtered to this external system's outbound API events. Audit rows
record the target by external-system name, so we filter on Target. *@
@if (Id.HasValue && !string.IsNullOrWhiteSpace(_name))
{
<a class="btn btn-outline-secondary btn-sm"
href="/audit/log?target=@Uri.EscapeDataString(_name)"
data-test="audit-link">
Recent audit activity
</a>
}
</div>
@if (_loading)
{