Checkpoint.AspNetCore
1.0.3
dotnet add package Checkpoint.AspNetCore --version 1.0.3
NuGet\Install-Package Checkpoint.AspNetCore -Version 1.0.3
<PackageReference Include="Checkpoint.AspNetCore" Version="1.0.3" />
<PackageVersion Include="Checkpoint.AspNetCore" Version="1.0.3" />
<PackageReference Include="Checkpoint.AspNetCore" />
paket add Checkpoint.AspNetCore --version 1.0.3
#r "nuget: Checkpoint.AspNetCore, 1.0.3"
#:package Checkpoint.AspNetCore@1.0.3
#addin nuget:?package=Checkpoint.AspNetCore&version=1.0.3
#tool nuget:?package=Checkpoint.AspNetCore&version=1.0.3
ASP.NET Core middleware for AI agent detection and policy enforcement. Drop-in middleware that detects AI agents, enforces policies from the Checkpoint dashboard, and blocks/redirects automated traffic. The .NET equivalent of @kya-os/checkpoint-express.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Checkpoint.Core (>= 1.0.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Checkpoint.AspNetCore:
| Package | Downloads |
|---|---|
|
KyaOs.Checkpoint
AI agent detection and policy enforcement for any .NET HTTP server. Install this metapackage and NuGet automatically pulls in the right adapter for your runtime: Checkpoint.AspNetCore on modern .NET (ASP.NET Core 6+), or Checkpoint.AspNet on classic .NET Framework 4.6.2+ (System.Web / IIS). Same WASM-backed Rust detection engine on both stacks — same patterns, same scoring, same updates. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.3 | 89 | 5/28/2026 |
| 1.0.2 | 122 | 5/27/2026 |
| 1.0.1 | 169 | 5/20/2026 |
| 1.0.0 | 170 | 5/18/2026 |
| 0.4.0 | 116 | 4/22/2026 |
| 0.3.3 | 193 | 4/21/2026 |
| 0.3.2 | 130 | 4/21/2026 |
| 0.3.1 | 118 | 4/18/2026 |
| 0.3.0 | 120 | 4/18/2026 |
| 0.2.9 | 113 | 4/18/2026 |
| 0.2.8 | 115 | 4/17/2026 |
| 0.2.7 | 112 | 4/17/2026 |
| 0.2.6 | 108 | 4/17/2026 |
| 0.2.5 | 119 | 4/17/2026 |
| 0.2.4 | 134 | 4/17/2026 |
| 0.2.3 | 120 | 4/17/2026 |
| 0.2.2 | 120 | 4/15/2026 |
| 0.2.1 | 112 | 4/15/2026 |
| 0.2.0 | 114 | 4/15/2026 |
| 0.1.11 | 100 | 4/13/2026 |
1.0.3 — Surface true enforcement outcomes on the dashboard
The .NET counterpart of the JS reporter fix shipped in
@kya-os/checkpoint-express + @kya-os/checkpoint-nextjs 1.4.0 (#2843).
Before 1.0.3 the .NET adapters posted detections to
/api/v1/log-detection without an `enforcement` block, so every
redirect / instruct / block applied by CheckpointModule (net462) or
CheckpointMiddleware (net8) landed in the dashboard as "unknown" on
the OutcomesBar / chart series — the operator could see traffic but
not what their middleware actually did with it.
Hardware World was the visible failure: with OnAgentDetected=Redirect
configured, ChatGPT/Claude hits 302'd to the connect page but the
dashboard never showed a redirect bar.
Fix: the adapters now thread the applied action into
`DetectionEvent.EnforcementAction` (+ optional Reason) at every
short-circuit and on the generic pass-through:
- Policy short-circuit: instruct | redirect | block
- Local config Block: "block" (+ result.BlockReason on policy block)
- Local config Instruct: "instruct"
- Local config Redirect: "redirect"
- Local config Redirect with non-absolute McpServerUrl: falls through
to "block" — the reported action reflects what HAPPENED (block),
not what was configured (redirect), so the chart doesn't show a
redirect that never occurred.
- Pass-through (Log / Allow): "log" in observe-mode (OnAgentDetected
= Log), "allow" otherwise. Mirrors the JS reporter's
`extractEnforcement()` Permit branch.
Canonical wire-action strings live in the new
`Checkpoint.Core.Configuration.EnforcementActions` static class so
both adapters report identical values — a typo would silently mis-
bucket as "unknown" rather than surface as the true outcome.
Migration: zero customer code changes required. The public API
(IAgentDetector, DetectionResult, CheckpointOptions, CheckpointModule,
CheckpointMiddleware) is unchanged. Bump the package version in
your csproj or packages.config; on the next request the dashboard
starts showing real redirect / instruct / block bars instead of
collapsing everything into "unknown".
8 new middleware tests + 6 new payload tests assert the action /
reason mapping for every branch (Block / Instruct / Redirect /
Redirect-fallthrough / Log / Allow / Policy-Redirect / Policy-Block).
1.0.2 — P0 latency hotfix: reactor-style WASM (Hardware-World-Hotfix-1)
CRITICAL FIX. Customer-reported regression on production deployment:
Hardware World (.NET Framework 4.8 + IIS + Web Forms) saw 22× median
slowdown and 50-second worst-case TTFB after installing 1.0.1.
Root cause: the embedded WASM shipped in 1.0.0–1.0.1 was a WASI
command-style module (`_start` entry point with stdin/stdout file
piping). Every HTTP request rebuilt the wasmtime Store/Linker/Instance,
did 6 filesystem operations, and — most importantly — re-ran every
`once_cell::Lazy` static in the Rust engine. With 123 `Regex::new`
calls in the pattern tables alone, per-call cost was ~84ms on the
fastest configuration (Apple Silicon + .NET 8 + SSD). On Windows + IIS
+ .NET Framework with NativeWasmtimeRuntime's P/Invoke layer, the
floor rose to 150-300ms and under concurrent load .NET Framework's
threadpool injection rate (~1-2 new workers/sec) cascaded into the
50s tail the customer observed.
Fix: the embedded WASM is now a reactor cdylib with three callable
exports — `engine_alloc`, `engine_dealloc`, `engine_verify_json`. The
host (both WasmtimeDotnetRuntime on net6.0+ and NativeWasmtimeRuntime
on netstandard2.0) instantiates ONCE and marshals JSON in/out via
linear memory. The engine's `Lazy` statics initialise once per WASM
instance and stay alive across calls.
Bench numbers (PerfBench harness, macOS .NET 8):
Metric 1.0.1 1.0.2 Improvement
----------------------------------------------------------------
Sequential median 84.1 ms 0.1 ms 840×
Sequential max 96.2 ms 0.5 ms 192×
Concurrent max (50 workers) 1842 ms 144 ms 13×
Throughput 12 c/s 6623 c/s 552×
Production on Windows + .NET Framework will see proportionally larger
wins because the contention amplification this avoids was higher
there.
Threading model: wasmtime Stores are not thread-safe. Both runtimes
keep one Store + Instance per thread via ThreadLocal<T>. First
call on each thread pays the lazy-init cost (~80ms); every subsequent
call on the same thread is <5ms. Under steady IIS load the
threadpool converges to a stable working set.
Other changes:
- Dropped Task.Run wrapper in WasmAgentDetector.AnalyzeAsync — the
per-call work is now CPU-bound and tiny; the threadpool detour
cost more than it saved.
- Dropped temp-file WASI stdin/stdout (no longer needed).
Migration: zero customer code changes required. The public API
(IAgentDetector, DetectionResult, CheckpointOptions, CheckpointModule)
is unchanged. Upgrade from 1.0.1 → 1.0.2 by bumping the package
version in your csproj or packages.config; no Web.config changes,
no Program.cs changes, no Web Forms code changes.
Embedded WASM SHA-256:
55e072f3ef71a2d548f935a292a07f8ab983eb4afa7ba5323f750b38845de33f
(was 800a314eb719bad54e94ee2fc94261110b7810be461adf83d4e6ea41eaf882ec
in 1.0.1; bump pinned in Checkpoint.Core.Tests/Detection/
EmbeddedWasmDriftTests.cs#ExpectedSha)
1.0.1 — Embedded engine refresh: post-#2685 TS-canonical pattern names
The embedded kya-os-engine.wasm shipped in 1.0.0 was built before
the Engine-Pattern-Codegen-Retirement-1 work (#2685) landed on main.
That work made the TS pattern registry the single source of truth and
codegen'd the Rust pattern table from it, which renamed several
canonical pattern IDs to match the TS convention:
GPTBot → "Openai Gptbot"
ClaudeBot → "Anthropic ClaudeBot"
(and similar vendor-prefixed forms across the AI crawler tier)
These names surface inside DetectionResult.DetectedAgent.Name,
DetectionResult.AgentType, and inside the detection signals + reasons
arrays consumed by the dashboard. The 1.0.0 .NET cohort was emitting
the pre-#2685 names; the Next.js + Express cohort (on
checkpoint-wasm-runtime@1.5.x) was emitting the post-#2685 names. The
delta showed up as detection-label drift between the two cohorts in
the dashboard.
1.0.1 re-bakes the embedded WASM from current main (kya-os-engine post
#2685) so every .NET deployment surface emits the same canonical
pattern names as the rest of the workspace. No public API change; no
new config knobs; no behavior change beyond the label correction.
Validation: this release is the first checkpoint-dotnet build covered
by the cross-runtime parity gate (#2708 / Cross-Runtime-Parity-Dotnet-
Coverage-1). The 4-runtime assert (rust + node-wasm + edge-wasm +
dotnet-wasi) catches exactly this class of stale-embedded-engine drift
before publish, so future .NET releases stay in lockstep automatically.
Embedded WASM SHA-256:
800a314eb719bad54e94ee2fc94261110b7810be461adf83d4e6ea41eaf882ec
(was 1626006e01b24a71de0f7476cb90349f06f80c0b52436a34e9dfdce470aa50d1
in 1.0.0; bump pinned in Checkpoint.Core.Tests/Detection/
EmbeddedWasmDriftTests.cs#ExpectedSha)
1.0.0 — Engine refresh: kya-os-engine replaces agentshield-core
The embedded WASM detection engine migrated from the legacy
agentshield-core / agentshield-wasi crates (last refreshed at v0.1.1)
to kya-os-engine — the same engine shipping in
@kya-os/checkpoint-wasm-runtime@1.4.x for Next.js + Express middleware
customers. .NET joins as the third host runtime on the unified engine.
The WASM binary, produced by rust/scripts/build-engine-wasi.sh from the
new kya-os-engine-wasi wrapper crate, drops from 7.2 MB (legacy) to
1.31 MB post wasm-opt — a 5.5× shrink. Lockstep upgrades for .NET
customers preserve every public API (IAgentDetector, DetectionResult,
CheckpointOptions, CheckpointModule) so existing customer code recompiles
unchanged.
What .NET customers gain:
- Tier 2 vendor IP + UA cross-match (16 vendor bots — Perplexity,
OpenAI x3, Anthropic x3, Google x3, Apple, Bing, DuckDuckGo x2,
Common Crawl). Surfaces via the new DetectionResult.VerifiedTier /
VerifiedVendor / VerifiedProtocol attribution fields.
- Tier 3 calibrated per-pattern confidence (replaces the legacy
single-knob ConfidenceThreshold misconfiguration footgun).
- Monitor-default Tier 3 behaviour: the engine classifies but does
NOT short-circuit a Block on a Tier-3 UA match. Tenant policy
decides enforcement. Opt-in to engine-default blocking via the new
CheckpointOptions.Tier3Action knob.
The .NET package's existing C# Tier 1 verifiers (ChatGptSignatureVerifier
RFC 9421, KyaAgentVerifier MCP-I JWS) are unchanged and continue to
pre-empt the WASM dispatcher for signed traffic.
Added:
- CheckpointOptions.Tier3Action (Monitor / Block / Challenge — default
Monitor)
- DetectionResult.VerifiedTier / VerifiedVendor / VerifiedProtocol
- kya-os-engine.wasm replaces agentshield-detect.wasm as the embedded
resource. Build via rust/scripts/build-engine-wasi.sh + commit the
refreshed bytes alongside the SHA pin update in
Checkpoint.Core.Tests/Detection/EmbeddedWasmDriftTests.cs.
Migration from 0.4.0:
- Existing CheckpointOptions configurations work unchanged.
- Empty-policy customers behave identically to 0.4.0 (Permit by default
on known agents — no breaking change).
- Customers wanting engine-level Tier 3 blocking explicitly set
Tier3Action.Block on CheckpointOptions.
Breaking changes: none at the public API surface. The embedded WASM is
replaced but the host code preserves the IAgentDetector + DetectionResult
+ CheckpointOptions contracts. The legacy wire format (detect action with
DetectionInput { headers, ip, method, url, tlsFingerprint }) is gone;
this is internal to WasmAgentDetector and not customer-observable.
0.4.0 — Normalize HTTP headers to KYA- convention
All custom response headers renamed from X-Checkpoint-* to KYA-*
per RFC 6648 (deprecated X- prefix) and the KYA-OS rebrand:
X-Checkpoint-Detected → KYA-Detected
X-Checkpoint-Confidence → KYA-Confidence
X-Checkpoint-Class → KYA-Class
X-Checkpoint-Agent → KYA-Agent
X-Checkpoint-Verification→ KYA-Verification
X-Checkpoint-Session → KYA-Session
MCP-I instruct response headers also renamed:
X-MCP-I-Required → KYA-Auth-Required
X-MCP-I-Authorize → KYA-Auth-Url
X-MCP-I-Project → KYA-Project
X-AgentShield-Action→ KYA-Action
rel="mcp-i-authorize" → rel="kya-authorize"
This is a BREAKING CHANGE for any consumer reading these headers
by name. No functional behavior changes.
0.3.3 — Remove legacy bouncer/sessions fallback + log log-detection failures
The 0.3.2 and earlier releases fell back from POST /api/v1/log-detection to
POST /api/v1/bouncer/sessions whenever the log-detection call returned
non-2xx. That fallback was semantically wrong: bouncer/sessions is the
MCP-I session registration endpoint and requires a real agent DID. The
fallback fabricated a synthetic "did:web:detected:{AgentType ?? unknown}"
DID per detection, which inserted junk rows into bouncer_sessions for
every crawler hit (Googlebot, aranhabot, Applebot, etc.) and emitted a
"[McpiConfigService] agentDid mismatch" warning on every row because the
synthetic DID collided with the project's real configured agentDid in
mcpiServerConfig.identity.
Production evidence from one project on 2026-04-21 showed ~17 junk
sessions/minute over a 70-second window (20 rows, 65% from "aranhabot"),
projecting to ~25k/day of pollution per active .NET middleware project.
Changes:
* CheckpointApiClient.ReportDetectionAsync no longer falls back to
bouncer/sessions. Non-2xx responses from log-detection are logged at
Warning with status code, reason phrase, project ID, and a bounded
512-char prefix of the response body, then dropped. Detection events
and MCP-I session registrations are distinct concerns and must not
be conflated.
* TryReportToLegacyAsync and its synthetic-DID payload construction
are deleted. ICheckpointApiClient.ReportDetectionAsync doc comment
updated to point at log-detection as the sole endpoint.
* New private helper SafeReadTruncatedBodyAsync reads at most 512 chars
of the failed response body and never throws, so high-volume failure
loops do not flood logs or leak large payloads.
No behavioural change when log-detection returns 2xx. Callers that were
relying on the legacy endpoint to persist detections should be on
Checkpoint.* >= 0.2.9 where log-detection is the documented path.
Operational follow-up (not in this release): after deploying 0.3.3,
clean up the existing junk rows with
DELETE FROM bouncer_sessions WHERE agent_did LIKE 'did:web:detected:%';
0.3.2 — Send detectionClass with log-detection payload
Pre-0.3.2 middleware submitted detection events to
POST /api/v1/log-detection without a detectionClass field. The server
falls back to isAgent ? "ai_agent" : "human", which mis-stamped every
Googlebot, GPTBot, ClaudeBot, SemrushBot, etc. hit as an interactive
AI agent. One hardwareworld.com test window produced 325,056 such
mis-classified rows under source="middleware" in 72 hours.
The detector already produces the correct class in
DetectionResult.DetectionClass. The gap was purely transport — the
DetectionEvent DTO and log-detection payload both dropped the field.
This release closes the gap:
* DetectionEvent gains a nullable DetectionClass property
(Checkpoint.Core). Nullable preserves binary compat for any caller
that constructs the DTO manually.
* CheckpointApiClient.TryReportToLogDetectionAsync now emits
detectionClass in the JSON payload via a wire mapping:
Human -> "human", AiAgent -> "ai_agent", Bot -> "bot",
IncompleteData/Unknown -> "incomplete_data". Null omits the field so
the server's UA-pattern fallback still applies for older callers.
* Both middlewares pass result.DetectionClass through to the
DetectionEvent — CheckpointMiddleware (AspNetCore, net8.0) and
CheckpointModule (AspNet, net462) share the same wiring.
Covers all four packages — Checkpoint.Core, Checkpoint.AspNet,
Checkpoint.AspNetCore, and the KyaOs.Checkpoint umbrella.
9 new tests:
* Checkpoint.Core.Tests/Api/CheckpointApiClientPayloadTests (7) —
per-enum wire assertions + null-omitted + endpoint URL.
* Checkpoint.AspNetCore.Tests/Middleware (2) — bot and AI-agent
DetectionClass pass-through from detector to DetectionEvent.
Follow-up (out of this release): harden the server fallback at
apps/web/app/api/v1/log-detection/route.ts so older clients that still
omit the field are classified via UA pattern instead of defaulted to
ai_agent.
0.3.1 — Block/Instruct response no longer leaks bad McpServerUrl
Follow-up to 0.3.0. The redirect branches in 0.3.0 correctly refused to
302 to a relative or non-http(s) McpServerUrl, but the block-response
body (PlainText "MCP Server: /connect/x" line, JSON "mcp_server" field)
and Instruct response still propagated the bad URL to the agent. An LLM
fetcher would relay the broken instructions to the user verbatim.
Changes:
* WritePlainTextResponseAsync (AspNetCore): McpServerUrl is gated through
UrlHelpers.IsAbsoluteHttpUrl — relative / non-http values are dropped
from the body and the agent gets the "contact site owner" fallback.
* WriteJsonResponseAsync (AspNetCore) + WriteBlockedJsonResponse (AspNet):
the "mcp_server" / "mcpServer" field is omitted (along with the
"instructions" sentence) when McpServerUrl is not an absolute http(s)
URL.
* WriteJsonResponseAsync + WriteInstructResponseAsync (AspNetCore):
switched from WriteAsJsonAsync to JsonSerializer.Serialize +
response.WriteAsync. The streaming serializer requires the response
body PipeWriter to implement UnflushedBytes, which TestServer's pipe
writer doesn't — every JSON-mode test in the AspNetCore suite was
silently throwing into FailOpen and falling through to the route
handler. Buffering matches what the AspNet adapter already does, and
resolves the four pre-existing test failures inherited from earlier
releases.
7 new tests in CheckpointMiddlewareTests covering Json/PlainText
McpServerUrl omission across path-relative, schemeless, protocol-relative,
javascript:, and ftp:// inputs. AspNetCore suite now 20/20 green
(was 9/13).