Basis.IntegrationPlatform.MessageStore 0.3.1

Prefix Reserved
dotnet add package Basis.IntegrationPlatform.MessageStore --version 0.3.1
                    
NuGet\Install-Package Basis.IntegrationPlatform.MessageStore -Version 0.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Basis.IntegrationPlatform.MessageStore" Version="0.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Basis.IntegrationPlatform.MessageStore" Version="0.3.1" />
                    
Directory.Packages.props
<PackageReference Include="Basis.IntegrationPlatform.MessageStore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Basis.IntegrationPlatform.MessageStore --version 0.3.1
                    
#r "nuget: Basis.IntegrationPlatform.MessageStore, 0.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Basis.IntegrationPlatform.MessageStore@0.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Basis.IntegrationPlatform.MessageStore&version=0.3.1
                    
Install as a Cake Addin
#tool nuget:?package=Basis.IntegrationPlatform.MessageStore&version=0.3.1
                    
Install as a Cake Tool

Basis .NET Message Store Adapter

Implements message-store contract v1.0.0-rc2 (basis-no/integration-platform-contract — spec, JSON Schemas, canonical SQL, and the certification suite both runtime adapters must pass).

NuGet package source for .NET integrations that need the Basis platform message-store contract.

Package (NuGet.org):

Basis.IntegrationPlatform.MessageStore

The adapter owns platform mechanics for .NET integrations:

  • consumes the platform input topic APP_KAFKA_INPUT_TOPIC (default bip.<APP_NAME>.in)
  • calls application code through IPlatformMessageHandler
  • takes the platform attempt number from the x-bip-attempt header (absent means attempt 1) and upserts the (message_id, attempt) row so infrastructure redeliveries re-record the same attempt
  • records terminal status in bip_message_log and bip_message_attempt
  • records per-attempt step observations (DELIVERED/FAILED/SKIPPED) in bip_message_attempt.steps_json
  • records idempotent external step outcomes in bip_step_outcome
  • stores replayable payload bytes in Postgres under the payload policy (replayable = payload captured, not expired, not deleted — independent of message status)
  • retries handler failures before terminal COMPLETED or DLQ
  • publishes failed messages to APP_KAFKA_DLQ_TOPIC (default bip.message.dlq) with x-bip-error and x-bip-dlq-at
  • exposes POST /admin/messages/{messageId}/resend
  • republishes replay payloads back to the integration input topic (bip.<integration>.in), committing the REQUESTED audit row before the Kafka produce
  • verifies the provisioned contract major in bip_contract at startup and refuses to start on a mismatch (missing table logs a loud warning during the v1.0 rollout)

Integration Usage

builder.Services.AddBasisMessageStoreAdapter<MyMessageHandler>();

app.MapBasisMessageStoreAdminEndpoints();

Application code implements:

public sealed class MyMessageHandler : IPlatformMessageHandler
{
    private readonly IPlatformStepExecutor steps;

    public MyMessageHandler(IPlatformStepExecutor steps)
    {
        this.steps = steps;
    }

    public async Task<PlatformMessageResult> HandleAsync(
        PlatformMessage message,
        CancellationToken cancellationToken)
    {
        await steps.ExecuteAsync(
            message,
            stepId: "target-system",
            endpointUri: "https://target.example/api/orders",
            targetRef: message.TargetSystem,
            operation: async ct =>
            {
                await SendToTargetSystem(message, ct);
            },
            cancellationToken);

        return PlatformMessageResult.Completed();
    }
}

Required Runtime Environment

The shared integration-app chart injects these when the catalog enables both Kafka and Postgres:

APP_NAME
APP_ENVIRONMENT
APP_TENANT
KAFKA_BOOTSTRAP_SERVERS
APP_KAFKA_INPUT_TOPIC
APP_KAFKA_DLQ_TOPIC
POSTGRES_JDBC_URL
POSTGRES_USERNAME
POSTGRES_PASSWORD
BASIS_MESSAGE_STORE_SINK
BASIS_MESSAGE_STORE_STEP_OUTCOME_STORE
BASIS_MESSAGE_STORE_REPLAY_INPUT_TOPIC_PATTERN

Payload policy

Identical semantics across runtime adapters (contract v1 §6):

Environment variable Default Meaning
BASIS_MESSAGE_STORE_PAYLOAD_MODE postgres_inline postgres_inline or metadata_only
BASIS_MESSAGE_STORE_PAYLOAD_MAX_BYTES 1048576 Payloads larger than this degrade to metadata_only with a replay_disabled_reason
BASIS_MESSAGE_STORE_PAYLOAD_RETENTION_DAYS 30 Sets payload_expires_at on captured payloads

metadata_only rows store no payload_bytes and are replayable=false with a reason. Replayability is a property of payload availability, never of the message outcome: COMPLETED messages are resendable as long as the payload is captured, unexpired, and undeleted.

Publish

Releases are published to NuGet.org as Basis.IntegrationPlatform.MessageStore by .github/workflows/publish-nuget.yml (tag-driven, NuGet Trusted Publishing). The workflow builds, tests against the vendored contract bip_* schema in tests/fixtures/postgres/, packs with the version derived from the tag, and pushes. Per ADR-003 the public registry is the canonical channel; tenant-registry fan-out remains an opt-in overlay for restricted environments and is operated from the platform's internal infrastructure.

License and support

Apache-2.0. The adapter is developed as part of the Basis integration platform; production use is supported for platform customers through their platform agreement. Issues and pull requests from other users are welcome and handled best-effort.

Managed payload capture profile

The managed runtime keeps the v1 Kafka consumer, Postgres lifecycle journal, step-outcome ledger, retry/DLQ handling and admin adapter active independently of payload storage. BASIS_MESSAGE_STORE_PAYLOAD_MODE=metadata-only processes messages but records no replay payload: lifecycle rows remain, with replayable=false and a reason. postgres-inline restores payload capture for subsequent deliveries subject to the existing size and retention policy.

This is not a no-storage mode: Kafka input/DLQ records retain their payloads under Kafka retention, and Postgres retains lifecycle and step metadata. Switching modes neither purges earlier history nor captures messages retroactively. Existing replayable history is evaluated per message by the adapter; a replay processed with capture off records a metadata-only new attempt. Earlier attempts and the replay audit remain historical evidence. The latest lifecycle row follows the latest attempt's capture policy.

Runtime stop/start remains deployment replica state. Do not disable the sink or step ledger to implement payload capture off: durable recording before commit remains mandatory. Missing or failed journal persistence must still prevent successful acknowledgement. No new adapter package or database schema is required for this profile; published .NET 0.3.0 and Camel 0.3.1 already implement the required payload modes. A coordinated managed projection release is required; do not infer fleet adoption from this documentation change.

Operator-owned runtime security

Existing deployments keep plaintext Kafka unless configured. For authenticated TLS, inject these settings through the platform's secret/runtime bindings:

Environment variable Default / purpose
BASIS_MESSAGE_STORE_KAFKA_SECURITY_PROTOCOL PLAINTEXT; use SASL_SSL for authenticated TLS (SSL, SASL_PLAINTEXT also recognized)
BASIS_MESSAGE_STORE_KAFKA_SASL_MECHANISM SCRAM-SHA-512; also SCRAM-SHA-256 or PLAIN
BASIS_MESSAGE_STORE_KAFKA_SASL_USERNAME Required for SASL; inject approved principal
BASIS_MESSAGE_STORE_KAFKA_SASL_PASSWORD Required for SASL; secret binding only
BASIS_MESSAGE_STORE_KAFKA_SSL_CA_LOCATION Mounted broker CA file; system trust if unset
BASIS_MESSAGE_STORE_POSTGRES_MAX_POOL_SIZE Optional bounded pool size for JDBC-derived settings; previous Npgsql default if unset
BASIS_MESSAGE_STORE_POSTGRES_SSL_MODE Optional Npgsql TLS mode, e.g. VerifyFull
BASIS_MESSAGE_STORE_POSTGRES_ROOT_CERTIFICATE Mounted PostgreSQL CA file

The same Kafka client configuration covers consumption, DLQ and replay. TLS certificate and hostname verification stay enabled. Missing SASL credentials fail validation; the client never silently falls back to plaintext. Keep credentials out of source, endpoint URLs and logs. An explicit POSTGRES_CONNECTION_STRING takes precedence and must carry its own pool/TLS settings. Plaintext modes are retained for trusted local compatibility.

Business persistence belongs in a separate application database. The adapter uses its keyed datasource PlatformMessageStoreExtensions.MessageStoreDataSourceKey for both journal and step persistence. A default datasource is still registered for backwards compatibility; registering another application datasource will not redirect adapter writes. Keep application schema migrations in a separate execution with a scoped migration login, never the Message Store login.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.1 94 9/28/2026
0.3.0 207 7/9/2026