Sigillum Finansdevelopers
Sigillum.cloud ↗TR
SDK integrations

.NET SDK reference

Package-level reference for installation, public interfaces, observation boundaries and delivery behaviour.

#Package and basic usage

Sigillum Finans .NET SDK 0.11.0

.NET 8, 9 and 10 use this normal net8.0 NuGet package and the same shared Java/.NET/Python observation contract. Official OpenTelemetry dependencies are mandatory package dependencies. Distribution is commercially licensed; public registry publication is separate from this package build.

#Normal ASP.NET Core setup

Reference Sigillum.Finans.Sdk.AspNetCore from the supplied local NuGet source; it references the core Sigillum.Finans.Sdk normally. The one .NET delivery ZIP contains the two Sigillum packages. NuGet resolves their declared third-party dependencies through the institution's normal package mirror. Worker/console projects use only the core package and do not require the ASP.NET Core shared runtime. Put the service-specific ready configuration at AppContext.BaseDirectory/.sigillum/config.json, or provide an explicit absolute configuration path. Add the normal package registration:

using Sigillum.Finans.Sdk;

builder.Services.AddSigillum();
builder.Services.AddHttpClient();
// After building the application, before handlers that consume request bodies:
app.UseSigillum();

The registration connects a ready handler to clients created by IHttpClientFactory; the middleware observes inbound ASP.NET Core requests. It does not require a second customer-owned helper project or hidden HTTP profile. A directly constructed HttpClient uses the supplied handler:

var client = new HttpClient(new SigillumHttpHandler(observer)
{
    InnerHandler = new HttpClientHandler()
});

Unread inbound requests are complete and empty only when native HTTP/1.0 or HTTP/1.1 framing proves no body: no Transfer-Encoding, and no Content-Length or one valid zero length. Finalization also requires no observed bytes/chunks or capture loss. The HTTP method alone never proves emptiness. Duplicate, conflicting or invalid framing, HTTP/2, HTTP/3 and unknown protocol metadata remain incomplete until native consumption proves completion. The SDK never reads, drains or rewinds a request to make this determination.

For a worker or batch, start the SDK once and use a configured named entry:

using var observer = new SigillumClient(absoluteConfigPath);
using var operation = observer.BeginOperation("configured-execution-name");
// Existing native work continues here.

Configuration, trust preparation and delivery run on the background worker. The business path does not wait for readiness, network, disk, a receipt or a flush. Dispose stops new capture without waiting for pending delivery. Calls made before configuration becomes ready are reported as observation loss; they are never presented as captured. Status distinguishes readiness, pending memory, verified durable custody, loss and retry attempts.

#Configuration

The shared sigillum.sdk-config/2 file contains these fields:

Field Meaning
formatVersion sigillum.sdk-config/2
institutionId, environmentId, serviceId Actual service scope; nonzero UUIDs
sourceToken This service's own source credential
transferEndpoint Exact HTTPS /api/transfer URL
rootCertificatePem Installation public CA; hostname checks remain enabled
custodyTrust keyId, spkiBase64, sha256Pin for the pinned P-256 custody receipt key
scopeTrust Pinned P-256 public key verifying product-issued execution scopes
contextKeyBase64 32-byte institution/environment propagation key
entryPoints Actual starts: applicationId, entryPointId, kind, operation, path, signed scopeToken
limits maxQueuedBytes, maxQueuedRecords, requestTimeoutMs, retryDelayMs, chunkBytes
localTransfer Optional product Agent endpoint (http://127.0.0.1:<port>) and a distinct 32–256 character printable ASCII token without spaces

With localTransfer, the SDK's observer worker sends bounded SFRAW001 raw captures to the installed Sigillum Agent at /v1/captures. Attachment hashes, observation envelopes, SFREC001 packaging, encryption, durable retry and upstream TLS run in that separate product process. Private official OTEL lifecycle and export still run on the SDK observer worker. Neither native capture nor application startup waits for the Agent. An unavailable local Agent retains the same bounded RAM retry behavior; it never activates a remote delivery fallback in the institution process. Failed local handoffs back off the endpoint with bounded exponential delay and small jitter, starting at the configured retry delay and capped at 30 seconds (or a larger configured delay). A valid local receipt resets the failure streak; direct-mode retries retain their existing configured fixed delay.

The exact HMAC-authenticated localDurable receipt releases pending SDK RAM only after the Agent's durable local handoff. Status.LocalDurableRecords counts these handoffs separately from Status.DurableRecords, which continues to count remote custody in direct mode. A local receipt is not final central evidence acceptance. Signed profiles come through the same Agent's /v1/profiles route and retain the existing scope signature and revision checks. Configuration without localTransfer retains direct HTTPS delivery.

An execution entry uses kind: execution, an exact operation and no path. An HTTP entry uses kind: http, an exact HTTP method and exact path. An already connected shared service can use entryPoints: []: its actual application and execution arrive in the signed observer carrier. Without a valid carrier or matching entry the SDK does not guess an application.

Each entry carries a product-signed, immutable application/service scope. The SDK verifies its P-256 signature, pinned key, institution/environment, actual entry identity and bounded service set on its worker before enabling roots. There is no unsigned or version-1 configuration fallback. Every root admission freezes that scope token and its UTC start time. Existing executions keep their original scope through all children and retries.

The background worker refreshes source profiles every 30 seconds from the same-origin authenticated /api/transfer/profiles endpoint. TLS, timeout and the 1 MiB response bound remain enforced. Only a fully verified monotonic registry revision replaces the active entry snapshot. The refresh is independent of delivery retry; business methods never perform configuration network I/O. Known source revocation stops new roots without rewriting accepted work.

A connected service excluded from an incoming execution's signed service set does not create spans, HTTP records, AI facts or reference records. It preserves the incoming observer span and can forward the authenticated carrier to the next connected service. Its returned scope has IsObserved == false; dispose it normally so that the previous ambient context is restored. This applies to BindContext and both synchronous and asynchronous HTTP calls. Inclusion in another application's scope does not expand the current application's scope.

Default limits are 64 MiB, 1024 records/active scopes, a 5000 ms worker request timeout, 1000 ms retry delay and 65536-byte stream chunks. Active private OTEL spans share the finite memory/slot budget. Pending encoded delivery and encoding workspace are included in conservative memory reservations. Queue capacity may be lowered, not raised above the shared 64 MiB/1024 ceiling.

#Public types and methods

SigillumClient is the service-wide observer. SdkOptions, SdkLimits, SdkEntryPoint and ReceiptTrust are the typed configuration alternatives. SdkOperation is a disposable execution/step scope; its Context is a detached public SdkContext snapshot containing actual execution and span IDs and the frozen ScopeToken. Reference arrays returned by Current or Context are detached from active and queued SDK records.

Method/property Use
BeginOperation(name) Begin a configured worker/batch execution; no login/session is required
BeginHttpOperation(method, path, incomingContext) Ready inbound HTTP boundary used by the middleware
BeginStep(name) Create a real child of the current observer scope
SdkOperation.Fail(exception) Record safe error type/cancellation; never read a virtual exception message
Current, ExportContext(), BindContext(carrier) Inspect/export/bind the signed independent observer context
SetReferences(SdkReferences) Add optional session/person/external references without merging executions
TryRecord(family, kind, rawJson, attachments, schema, links) Generic actual fact with an extensible raw JSON object
Model, Classification, Retrieval, Tool, Embedding Named AI fact helpers accepting raw JSON
Inference, Evaluation, Policy, Explanation Prediction/control/source-produced explanation helpers
Source, Custom Source comparison/custom fact plus optional exact content
ObserveAiAsync(name, rawInput, nativeCall, token) Invoke one native call once; capture supplied input and returned raw output; preserve the native exception/cancellation
TrySetOtelAttribute, TryAddOtelEvent, TryAddOtelLink Bounded enrichment of the SDK's real private OTEL span
Status Ready, queued records/bytes, remote custody records, local durable handoffs, lost records, failed attempts and last observer error

The generic families are lifecycle, ai, http, otel, context, source and custom. Their contents retain actual field names, absent fields, explicit nulls, arbitrary precision numeric lexemes and extension fields. The returned capture boolean acknowledges bounded RAM admission only. Raw JSON object/depth/duplicate validation runs on the observer worker. Invalid admitted data is never delivered; its reservation is released and an explicit encoding loss report is queued under the original frozen execution scope. The SDK does not call arbitrary object getters, enumerate lazy application objects or infer a model's hidden reasoning. Use already materialized UTF-8 JSON and arrays, rather than application object serialization.

observer.Classification("""
    {"intent":"actual-source-intent","score":0.9876543210987654321}
    """u8.ToArray());

observer.SetReferences(new SdkReferences(
    SessionRef: existingSessionReference,
    PersonRef: existingPersonReference,
    External: [new("institution.trace", existingTraceReference)]));

SdkAttachment(Id, MediaType, Purpose, Bytes) carries exact binary/text bytes. SdkLink(TraceId, SpanId, Relation) carries actual explicit links. Content bytes are copied under the admission budget, then hash/length/exact-byte references are generated by the worker. Standard capture allows JSON objects up to 8 MiB minus envelope overhead, depth 32, up to 128 attachments of at most 16 MiB each, subject to the total 32 MiB packet and finite queue budget. Oversize, malformed or saturated observations fail capture and report loss; they do not throw into native work or silently become complete records.

OTEL attribute helpers accept known scalar or homogeneous primitive-array JSON values. Events and links accept JSON objects of those attributes. These use OTEL's actual integer/double value types; use the generic raw JSON fact surface when exact arbitrary-precision number lexemes are required. Each helper reserves memory before retaining values, releases replacement credit, and reports capacity rejection. Limits are 1024 attributes, 1024 events, 1024 links and 4096 primitive array elements, always subject to the shared byte budget. No independent source string truncation is applied. Up to 64 external references are accepted. No raw private Activity is exposed.

#Automatic capture and delivery

Supported HTTP boundaries capture method, target, headers, response status, actual consumed request/response bytes, stream chunks/offsets/terminal state, safe error/cancellation type and actual ancestry. Bodies are not read ahead. Both HttpClient.Send and SendAsync use the same capture contract and invoke the native transport once. Native synchronous content serialization and stream access remain synchronous. Successful stream repositioning or resizing is marked partial; a reposition after an earlier terminal appends an explicit loss fact rather than rewriting history. Header capture allows 4096 name/value pairs and 1 MiB total UTF-8 names/values; over-capacity output explicitly states complete: false and reports loss. Header snapshots and JSON workspace reserve the same finite ledger before copying. A wrapped content object's header-copy credit remains held until the application disposes that content. If credit is unavailable, the native content remains unchanged and the observation loss stays explicit. Disposal before EOF, capacity loss and incomplete consumption remain partial. The native value, exception, cancellation token and stream ownership remain with the application. Existing traceparent/tracestate headers and native OTEL providers, samplers/exporters and Activity.Current are preserved.

Each SDK instance owns an always-on private OTEL provider/source with its own configuration, independent of institution OTEL environment/sampler settings. All official Activity start/stop and listener callbacks run on the observer worker. The business path creates only bounded product execution/span context and immutable facts. A slow global institution listener can stall observation delivery but cannot enter the business call through this instrumentation.

Actual private spans include resource, instrumentation scope, attributes, events, links, status and actual dropped/observation limit counts. Their real OTEL IDs are explicitly exposed as nativeContext, and the product's causal IDs as observerContext. A labelled observer-context link connects them; the IDs are never falsely presented as identical. Explicit source facts retain institutionProvided origin; automatic HTTP/lifecycle facts use sdkAutomatic, and real OTEL spans use nativeOtel.

The independent x-sigillum-context v2 carrier is scope checked and MAC verified. Its frozen scope token is independently signature verified; possessing the institution's propagation MAC key does not authorize a different service set. It always includes an optional-reference object. If references would exceed the 16 KiB wire limit, only their propagation is omitted; all original local facts are retained, the signed causal core continues, and referencePropagationPartial is reported. Active references are not changed. It is observation metadata, never business authorization. SDK-free components are not inspected; if they pass the carrier, connected endpoints keep the actual relationship. Parallel calls remain separate children. Missing context is never reconstructed by time, content, person or session equality.

The worker batches only already-ready records from the same execution and frozen profile, at most 16 records and 8 MiB without waiting for a threshold. A larger valid single record travels alone within the 32 MiB transport bound. It retries identical packet bytes and delivery ID. A failed packet stays in the same byte/slot reservation and waits its backoff in a fair bounded retry rotation; it does not prevent other executions from reaching durable custody. No retry creates another copy of the pending packet or releases its credit before a verified receipt. Only an actual root-span record from its own root service repeats the immutable root admission. Child-span batches keep an empty admission list, including children in that same process; a shared-service continuation never invents a foreign admission. The memory copy is released only after the exact scoped record/package/delivery bindings and pinned P-256 custody receipt verify. This receipt proves durable product custody, not final central publication. RAM before that receipt is not durable and can be lost on process failure. The product-owned transfer worker performs durable encrypted storage and subsequent retries. The observer delivery transport uses at most one concurrent IPv4 and one IPv6 connection attempt, cancelling and disposing the losing connection. The original hostname, TLS server name and strict installation CA checks remain intact. This configuration never changes the application's HTTP client.

Sigillum Finans · Source-matched product reference

Search documentation

Search titles and content by entering a topic.

↑ ↓ select · Enter open · Esc closeBrowser-local search