Sign inSign up

jchristn77/netledger

By jchristn77

Updated about 1 month ago

Ledgering API server for financial systems.

Image
Developer tools
Databases & storage
0

2.6K

jchristn77/netledger repository overview

NetLedger

NuGet Version NuGet Downloads License

NetLedger is a thread-safe ledgering library for .NET 8.0 and .NET 10.0 that provides tenant-aware debit/credit workflows with auditable pending and committed entry lifecycles. It supports SQLite for embedded deployments and MySQL, PostgreSQL, and SQL Server for external database deployments.

Screenshots

Screenshot 1

Screenshot 2

Screenshot 3

Screenshot 4

Screenshot 5

v3.0.0

NetLedger v3.0.0 is the tenant-aware release. Public objects now use PrettyId string IDs such as acct_..., ent_..., ten_..., usr_..., and cred_...; accounts and entries carry TenantId; and account/entry metadata can be set with Labels and Tags.

What is new in v3.0.0:

  • Multi-tenancy: tenant, user, credential, session, role, permission, account-user mapping, and audit-record domain models.
  • Tenant-scoped ledger data: accounts, entries, balances, commits, pending entries, credentials, users, sessions, audit records, roles, and permissions can be scoped by tenant.
  • Tenant-aware APIs: /v1/tenants/{tenantId}/... route aliases and x-tenant-id support preserve existing /v1 paths while making tenant scope explicit.
  • PrettyId identifiers: public models now use K-sortable string IDs with prefixes such as acct_, ent_, ten_, usr_, and cred_.
  • Metadata on accounts and entries: List<string> Labels and Dictionary<string,string> Tags are available in library models, REST payloads, SDKs, Postman, and dashboard forms.
  • Metadata search and enumeration: account and entry searches can filter by labels and tags; entry enumeration also supports debit/credit amount bounds and amount/date ordering.
  • Authentication and authorization: tenant discovery, email/password login, revocable server-side sessions, credential rotation/revocation, RBAC role assignment, and effective-permission checks.
  • Dashboard v3 workflows: tenant-aware login, tenant/user/account filtering, account and entry metadata editors, label badges, formatted tag display, reveal controls for hidden secrets, and automatic return to login when authentication fails.
  • Dashboard charts: Home now shows Value Recorded, Transactions over Time, and Amounts over Time with shared tenant/user/account/range controls, fixed time-bucket fidelity, and bounded hover tooltips; Request History includes a taller Traffic over Time chart with matching hover behavior.
  • API tooling: OpenAPI is served at GET /openapi.json, the dashboard API Explorer executes requests with the signed-in session, REST_API.md and Postman cover tenant and metadata filters, and the .NET, JavaScript/TypeScript, and Python SDKs expose v3 search/enumeration options.
  • Touchstone-backed tests: shared suites run through Test.Shared, Test.Automated, Test.Xunit, and Test.Nunit for provider certification and behavior coverage.

Authentication flow:

  1. Call POST /v1/auth/tenants with { "Email": "[email protected]" }.
  2. If multiple tenants are returned, select the tenant to enter.
  3. Call POST /v1/auth/login with tenant ID, email, and password.
  4. Send the returned Session.Token as Authorization: Bearer <token> and send x-tenant-id for tenant-scoped requests.

Credential management is available through /v1/credentials and tenant-scoped credential routes. The legacy /v1/apikeys management paths are removed in v3.

Minimal v3 library example:

using NetLedger;

await using Ledger ledger = new Ledger("accounting.db");

string accountId = await ledger.CreateAccountAsync("Operating Account", 1000.00m);

await ledger.AddCreditAsync(accountId, 500.00m, "Customer payment");

Balance balance = await ledger.CommitEntriesAsync(accountId);

Who Should Use NetLedger

NetLedger is designed for developers building applications that require:

  • Tenant-Aware Ledger Workflows - Scope accounts, entries, balances, users, credentials, sessions, roles, permissions, and audit records by tenant.
  • Controlled Financial Entry Lifecycles - Keep pending entries separate from committed entries, then explicitly commit reviewed debits and credits.
  • Auditable Account Balances - Maintain balance-entry chains that support point-in-time balance reads and integrity verification.
  • Role-Aware API Access - Build systems with system admins, tenant admins, and account-scoped users using sessions, credentials, RBAC assignments, and effective-permission checks.
  • Metadata-Driven Search - Attach labels and tags to accounts and entries, then filter and enumerate by metadata, amount bounds, timestamps, and ordering.
  • Database Choice - Use SQLite for embedded/local deployments or MySQL, PostgreSQL, and SQL Server for external database deployments.
  • Concurrent Account Writes - Serialize writes to the same account while allowing independent accounts to proceed in parallel.
  • API, Dashboard, and SDK Integration - Use the core .NET library directly or integrate through the REST server, dashboard, Postman collection, and .NET, JavaScript/TypeScript, and Python SDKs.
  • Async .NET Applications - Use async APIs with cancellation-token support throughout the library and server.

Ideal use cases: Financial applications, expense tracking systems, point-of-sale systems, accounting software, multi-user financial platforms, billing systems, payment processing, and applications requiring account-level debit/credit ledgers with strong auditability.

What NetLedger Does

Core Capabilities
  • Tenant Management - Create and enumerate tenants, users, sessions, credentials, account-user mappings, roles, permissions, and audit records.
  • Authentication and Authorization - Tenant discovery, email/password login, revocable sessions, credential management, admin flags, RBAC assignments, effective-permission checks, and scoped API access.
  • Account Management - Create, retrieve, search, enumerate, update, and delete tenant-scoped accounts with optional initial balances.
  • Account and Entry Metadata - Attach normalized labels and key/value tags to accounts and entries.
  • Transaction Operations - Add credits and debits as pending entries or immediately committed entries.
  • Batch Operations - Process multiple credits or debits in a single account-scoped batch.
  • Dual Balance Tracking - Separate committed balance from pending/projected balance.
  • Selective Commits - Commit all pending entries or a specific set of entries.
  • Entry Cancellation - Cancel pending entries before they are committed.
  • Powerful Enumeration - Filter accounts and entries by tenant, account, text, timestamps, amount bounds, debit/credit-specific bounds, labels, tags, and ordering.
  • Pagination Support - Use skip/limit and continuation-token enumeration patterns for large result sets.
  • Point-in-Time Balances - Calculate balances as of a historical timestamp.
  • Balance Chain Verification - Validate audit-trail integrity across balance entries.
  • REST API, Dashboard, and SDKs - Use NetLedger through the .NET library, REST server, dashboard, Postman collection, and .NET, JavaScript/TypeScript, and Python SDKs.
  • Request History and Charts - Capture request history and summarize dashboard chart data over fixed time buckets.
  • Supported Databases - SQLite, MySQL, PostgreSQL, and SQL Server providers are included.
  • Concurrent Write Safety - Entries for the same account are serialized with in-process and database-backed account locks, while different accounts can proceed independently.
What NetLedger Does NOT Do
  • Double-Entry Accounting - NetLedger is an account-level debit/credit ledger. It does not enforce balanced journal entries across two or more accounts.
  • Multi-Currency Accounting - Amounts are numeric ledger values; currency codes, FX rates, and currency conversion are application responsibilities.
  • Automatic Transfers - There is no built-in transfer primitive that atomically debits one account and credits another account as a balanced pair.
  • Transaction Reversal Workflow - Committed entries are not undone in place; create offsetting entries when a business reversal is required.
  • Scheduled or Recurring Transactions - NetLedger does not schedule future-dated or recurring entries.
  • Account Hierarchies - Accounts do not have built-in parent/child rollup relationships.
  • Budget Enforcement - Spending limits, approvals, and budget controls are application-level concerns.
  • Arbitrary Custom Columns - Accounts and entries have a defined schema. Use labels and tags for supported metadata filtering rather than adding arbitrary fields.
  • Cross-Database Transactions - NetLedger does not coordinate a transaction across multiple independent database instances.

Quick Start

Choose the approach that best fits your needs:

Option 1: NuGet Package (Library Integration)

Install the library directly into your .NET application:

dotnet add package NetLedger

Or via NuGet Package Manager:

Install-Package NetLedger

Then use it in your code:

using NetLedger;

// Initialize ledger (creates or opens SQLite database)
Ledger ledger = new Ledger("accounting.db");

// Create an account with optional initial balance
string accountId = await ledger.CreateAccountAsync("Operating Account", 1000.00m);

// Add a pending credit
string creditId = await ledger.AddCreditAsync(accountId, 500.00m, "Customer payment");

// Add a pending debit
string debitId = await ledger.AddDebitAsync(accountId, 150.00m, "Supplier invoice");

// Check balances before commit
Balance balance = await ledger.GetBalanceAsync(accountId);
Console.WriteLine($"Committed: ${balance.CommittedBalance}");  // 1000.00
Console.WriteLine($"Pending: ${balance.PendingBalance}");      // 1350.00

// Commit all pending entries
balance = await ledger.CommitEntriesAsync(accountId);
Console.WriteLine($"Committed: ${balance.CommittedBalance}");  // 1350.00

// Cleanup
await ledger.DisposeAsync();
Option 2: Build and Run from Source

Clone the repository and build locally:

# Clone the repository
git clone https://github.com/jchristn/NetLedger.git
cd NetLedger

# Build the solution
dotnet build src/NetLedger.sln

# Run the interactive test application
dotnet run --project src/Test/Test.csproj

# Run the automated test suite against SQLite
dotnet run --project src/Test.Automated/Test.Automated.csproj -- --type sqlite

# Run the REST API server
dotnet run --project src/NetLedger.Server/NetLedger.Server.csproj
Option 3: Docker

Run NetLedger Server and Dashboard using Docker Compose:

# Navigate to the docker directory
cd docker

# Start the server and dashboard
docker compose up -d

# View logs
docker compose logs -f

This starts:

  • NetLedger Server on http://localhost:8080 - REST API server
  • NetLedger Dashboard on http://localhost:3000 - Web-based management UI

Fresh deployments create tenant default with admin@netledger / password.

To stop the services:

docker compose down
Docker Configuration

The Docker setup uses configuration files in the docker/server/ directory:

netledger.json - Server configuration:

{
  "Webserver": {
    "Hostname": "+",
    "Port": 8080,
    "Ssl": false
  },
  "Logging": {
    "EnableConsole": true,
    "LogRequests": true
  },
  "Authentication": {
    "Enabled": true,
    "DefaultAdminKey": "netledgeradmin"
  },
  "Database": {
    "Type": "Postgresql",
    "Hostname": "postgres",
    "Port": 5432,
    "Username": "netledger",
    "Password": "netledger",
    "DatabaseName": "netledger",
    "Schema": "public",
    "RequireEncryption": false,
    "ConnectionTimeoutSeconds": 30,
    "MaxPoolSize": 100,
    "LogQueries": false
  }
}

Dashboard

NetLedger includes a web-based dashboard for managing accounts and viewing transactions.

Starting the Dashboard

With Docker (recommended):

cd docker
docker compose up -d

For development:

cd src/NetLedger.Dashboard
npm install
npm run dev
Accessing the Dashboard
  • Docker: Open http://localhost:3000 in your browser
  • Development: Open http://localhost:5173 in your browser (Vite default port)

The dashboard provides:

  • Tenant, user, credential, account, and entry management based on the signed-in user's role
  • Transaction entry (credits and debits)
  • Label and tag metadata entry for accounts and entries
  • Balance viewing and history
  • Home charts for Value Recorded, Transactions over Time, and Amounts over Time with shared range, tenant, user, and account controls
  • Chart hover tooltips with timestamp/value detail and fixed time-bucket fidelity for last hour, day, week, and month views
  • Entry search and enumeration by tenant, account, description, date range, amount bounds, labels, tags, and ordering
  • Entry commit operations
  • API Explorer backed by GET /openapi.json
  • Request History with filters, summaries, detail views, scoped deletion for admins, and a Traffic over Time chart

SDKs

NetLedger provides official SDKs for integrating with the REST API server:

.NET SDK
dotnet add package NetLedger.Sdk
using NetLedger.Sdk;

// Create a client with a session token or credential access key.
using NetLedgerClient client = new NetLedgerClient("http://localhost:8080", "netledgeradmin", "default");

// Create an account
Account account = await client.Account.CreateAsync("My Account");

// Add credits and debits
await client.Entry.AddCreditAsync(account.Id, 100.00m, "Deposit");
await client.Entry.AddDebitAsync(account.Id, 25.50m, "Purchase");

// Get balance and commit
Balance balance = await client.Balance.GetAsync(account.Id);
await client.Balance.CommitAsync(account.Id);

// API Explorer and Request History support
string openApiJson = await client.Service.GetOpenApiJsonAsync();
EnumerationResult<RequestHistoryEntry> history = await client.RequestHistory.EnumerateAsync(new RequestHistoryQuery { MaxResults = 25 });

See sdk/sdk-csharp/NetLedger.Sdk/README.md for full documentation.

JavaScript/TypeScript SDK
npm install netledger-sdk
import { NetLedgerClient } from 'netledger-sdk';

// Create a client with a session token or credential access key.
const client = new NetLedgerClient('http://localhost:8080', 'netledgeradmin', { tenantId: 'default' });

// Create an account
const account = await client.account.create('My Account');

// Add credits and debits
await client.entry.addCredit(account.Id, 100.00, 'Deposit');
await client.entry.addDebit(account.Id, 25.50, 'Purchase');

// Get balance and commit
const balance = await client.balance.get(account.Id);
await client.balance.commit(account.Id);

// API Explorer and Request History support
const openApiSpec = await client.service.getOpenApiSpec();
const history = await client.requestHistory.enumerate({ MaxResults: 25 });

See sdk/sdk-js/README.md for full documentation.

REST API

When running NetLedger Server (via Docker or directly), a full REST API is available for programmatic access.

Base URL: http://localhost:8080

Authentication: User sessions and credentials are accepted as bearer tokens via Authorization: Bearer <token-or-access-key>. Credential authentication can also use x-access-key and x-secret-key. Tenant scope can be supplied with x-tenant-id or tenant-scoped routes.

Quick Examples
# Health check
curl http://localhost:8080/

# Create an account with label/tag metadata
curl -X PUT http://localhost:8080/v1/accounts \
  -H "Authorization: Bearer netledgeradmin" \
  -H "x-tenant-id: default" \
  -H "Content-Type: application/json" \
  -d '{"Name":"My Account","InitialBalance":100.00,"Labels":["operating","blue"],"Tags":{"department":"finance","color":"blue"}}'

# Add a credit with label/tag metadata
curl -X PUT http://localhost:8080/v1/accounts/{accountId}/credits \
  -H "Authorization: Bearer netledgeradmin" \
  -H "x-tenant-id: default" \
  -H "Content-Type: application/json" \
  -d '{"Amount":50.00,"Notes":"Customer payment","Labels":["blue"],"Tags":{"color":"blue"}}'

# Search entries by amount bounds, label, tag, and ordering
curl "http://localhost:8080/v1/accounts/{accountId}/entries?debitMin=5&debitMax=50&labels=blue&tags=color=blue&ordering=AmountDescending" \
  -H "Authorization: Bearer netledgeradmin" \
  -H "x-tenant-id: default"

# Get balance
curl http://localhost:8080/v1/accounts/{accountId}/balance \
  -H "Authorization: Bearer netledgeradmin" \
  -H "x-tenant-id: default"

# Commit pending entries
curl -X POST http://localhost:8080/v1/accounts/{accountId}/commit \
  -H "Authorization: Bearer netledgeradmin" \
  -H "x-tenant-id: default" \
  -H "Content-Type: application/json" \
  -d '{}'

For complete API documentation, see REST_API.md.

License

MIT License - See LICENSE.md for details

Version History

v3.0.0 (Current)
  • Tenant-scoped ledger data, authentication, authorization, credentials, sessions, RBAC, and audit records.
  • PrettyId string identifiers on public models.
  • Account and entry labels/tags with metadata-aware search and enumeration.
  • SQLite, MySQL, PostgreSQL, and SQL Server providers.
  • Dashboard charts, request history, API Explorer, Touchstone-backed tests, LoadGenerator, REST API docs, Postman, and SDK updates.

See CHANGELOG.md for complete version history.

Tag summary

Content type

Image

Digest

sha256:e7ddee4f3

Size

129.1 MB

Last updated

about 1 month ago

docker pull jchristn77/netledger