DOSSIER 002 · FIELD NOTES

< All entries

FILED 2026.10.16
AUTH · J. MIDDLER

Bower: only the security events you meant to send, with Australian PII removed first

A self-hosted gateway that picks approved security events from custom apps, strips Australian identifiers and secrets on the host, and proves they arrived in Microsoft Sentinel.

Bower collects security events from custom applications and legacy products that don't plug cleanly into Microsoft Sentinel. It keeps only the event types an approved policy names, removes Australian personal data and secrets on the host before anything is stored, and delivers the result through Azure Monitor Agent files or the Logs Ingestion API. Then it proves the events actually turned up in Sentinel.

The name comes from the bowerbird, which picks and arranges what it wants rather than hoarding everything.

Why I built it

Log shippers move logs. That's useful, but it leaves three problems for teams running Sentinel in Australia.

The first is noise. Forwarding everything and filtering later costs money and buries the events that matter. Bower is default deny: if an approved, versioned policy doesn't name an event type, it's rejected and the reason is recorded.

The second is personal data. Redaction usually happens after the data has already left the host. Bower's Privacy & Secret Protection Engine runs before anything is persisted, using deterministic pattern matching and checksum validation, with no AI at runtime. It knows TFNs (the ATO 8 and 9 digit checksum), Medicare numbers, IHIs, Centrelink CRNs, ABNs and ACNs, plus payment cards, cloud credentials, JWTs, API keys and private keys. Each detector has its own action, such as mask, hash, HMAC or remove. If a check fails, the event is quarantined. High-risk finds also raise a sensitive_data_detected event so the SOC can alert on it, without the original value.

The third is proof. Most tools stop once the API accepts the upload. Azure can still truncate or drop rows without telling you.

How it works

The flow is collect, select, arrange, deliver and prove. An application or source produces a candidate event. It goes through the privacy engine, then schema validation, then the policy. Accepted events land in a durable SQLite queue that only deletes after acknowledgement, with dead letters and replay. The queue keeps a hash-chained ledger whose head is witnessed by the management plane, so tampering shows.

Developers instrument their apps with the .NET SDK:

await bower.AuthenticationFailedAsync(
    new AuthenticationFailedEvent
    {
        Username = request.Username,
        SourceIpAddress = httpContext.Connection.RemoteIpAddress,
        FailureReason = "InvalidPassword",
        CorrelationId = httpContext.TraceIdentifier
    },
    cancellationToken);

bower developer init writes AGENTS.md guidance into a repo so coding agents instrument events the same way.

For proof, bower evidence run sends a canary event, finds it in Sentinel with KQL, records latency and retention, maps it to ISM and Essential Eight controls and signs the result. bower doctor and the DCR drift checks catch config problems before they eat data.

There's also a management console with fleet inventory, approvals, health, audit history and Entra ID role-based access, a Docker sidecar for opted-in containers, a SQL Server source adapter, and a cloud agent that brings in AWS GuardDuty, Security Hub and CloudTrail plus Google Cloud Security Command Center and admin audit logs through the same redaction and policy.

Where it's at

It's pre-alpha and not production-ready. The pieces above are built. File, REST and Windows Event Log sources aren't yet, and a full evidence run against a real tenant is still on the list before v1. The README is clear that no mocked upload counts as Sentinel delivery.

Try it

You'll need the .NET 10 SDK. Everything below uses synthetic data:

dotnet build --configuration Release
BOWER_QUEUE_PATH=./artifacts/bower.db \
BOWER_POLICY_DIRECTORY=./policies/default \
BOWER_OUTPUT=ama-spool \
BOWER_AMA_SPOOL_PATH=./artifacts/spool \
dotnet run --project src/Bower.Collector

Then in another shell:

dotnet run --project src/Bower.Cli -- test emit

You'll see the policy decision, and the redacted event lands as JSONL in the spool folder. Images for the collector, management API, console, sidecar and cloud agent are on GHCR (ghcr.io/jusso-dev/bower-collector:edge and friends). The code is MIT licensed at github.com/jusso-dev/Bower.

// END OF ENTRY //
ENTRY BOWER
STATIC EXPORT