Skip to content

Backend: Add jurisdiction-aware compliance reporting with config-driven rules engine#155

Merged
ludovit-scholtz merged 5 commits intomasterfrom
copilot/add-compliance-reporting-api
Feb 5, 2026
Merged

Backend: Add jurisdiction-aware compliance reporting with config-driven rules engine#155
ludovit-scholtz merged 5 commits intomasterfrom
copilot/add-compliance-reporting-api

Conversation

Copy link
Contributor

Copilot AI commented Feb 5, 2026

Summary

Implements backend infrastructure for jurisdiction-specific compliance reporting and audit exports to support regulated RWA tokenization. Existing compliance reports and audit trails remain unchanged; this adds jurisdiction tagging and evaluation capabilities.

Architecture

Configuration-driven rules - Jurisdictions defined as data, not code:

// Seeded rules: EU MICA (Articles 17,18,20,23,30) + GLOBAL FATF (KYC/AML)
// Add new jurisdictions via API without deployment
POST /api/v1/compliance/jurisdiction-rules

Multi-jurisdiction tokens - One primary, multiple secondary:

// Token can be EU primary, US secondary
POST /jurisdiction-rules/assign?assetId=123&jurisdictionCode=EU&isPrimary=true

Automatic evaluation - Aggregates all applicable rules:

// Returns: Compliant|PartiallyCompliant|NonCompliant|Unknown
// With per-requirement evidence and rationale
GET /jurisdiction-rules/evaluate?assetId=123&network=voimain-v1.0

Key Components

Models (JurisdictionRules.cs)

  • JurisdictionRule - Priority-based rule with active/inactive flag
  • ComplianceRequirement - Individual checks with severity (Critical|High|Medium|Low|Info)
  • TokenJurisdiction - Multi-jurisdiction assignment with primary designation
  • JurisdictionEvaluationResult - Aggregated status with check-by-check rationale

Repository (JurisdictionRulesRepository.cs)

  • In-memory ConcurrentDictionary for thread-safe operations
  • Auto-seeds EU MICA (6 requirements) and GLOBAL FATF (2 requirements)
  • Supports pagination, filtering by jurisdiction/framework/active status

Service (JurisdictionRulesService.cs)

  • Evaluates KYC/AML verification status from ComplianceMetadata
  • Falls back to GLOBAL baseline when no jurisdiction assigned
  • Integrates with existing ComplianceRepository for evidence lookup

Controller (JurisdictionRulesController.cs)

  • 9 REST endpoints: CRUD + evaluate + token assignments
  • ARC-0014 authentication required
  • Input sanitization via LoggingHelper

Integration

Enhanced ComplianceReportService constructor to accept IJurisdictionRulesService for future jurisdiction-aware report generation. Existing report generation logic unchanged.

Security

  • Zero CodeQL alerts
  • All logs sanitized (prevents log injection)
  • Issuer-level access control enforced
  • Thread-safe concurrent collections

Backward Compatibility

All changes additive. Existing compliance reports, audit trails, and metadata APIs unchanged. Tokens without jurisdiction assignment automatically use GLOBAL baseline.

Original prompt

This section details on the original issue you should resolve

<issue_title>Backend: Compliance reporting & jurisdiction-aware audit exports</issue_title>
<issue_description>## Summary

This issue proposes a backend initiative for the Biatec Tokens API to deliver reliable, compliant, and auditable compliance reporting and jurisdiction-aware enforcement. The current platform vision centers on regulated real‑world asset tokenization with enterprise‑grade compliance, yet backend coverage for compliance reporting, jurisdiction tracking, and automated audit outputs is incomplete. We need a cohesive backend feature set that exposes compliance state, audit artifacts, and readiness signals to the frontend and external integrators in a consistent, secure API. This issue focuses on building the API contracts, data models, and background processing needed for compliance reporting and audit trail export, plus a minimal but extensible jurisdiction rules engine that can be consumed by UI and external systems. The intent is to de‑risk regulatory adoption and reduce the gap between the current MVP state and the Phase 2 enterprise compliance vision outlined in the business owner roadmap.

Business Value

The Biatec Tokens business model targets subscription revenue from enterprise and professional customers who require credible compliance tooling. At present, the roadmap highlights partial implementation of compliance reporting, jurisdiction tracking, and regulatory integration. Without a reliable backend for compliance artifacts, the platform cannot credibly sell enterprise plans, and it risks churn among early adopters who must meet MICA requirements. A backend compliance reporting service becomes a differentiator because competitors often show surface‑level badges but cannot produce auditable proof or machine‑readable compliance exports. This capability directly improves conversion for regulated institutions, accelerates sales cycles, and supports higher pricing tiers. It also reduces support costs by enabling standardized exports that auditors and regulators can consume without bespoke manual effort.

From a market perspective, the RWA tokenization segment is growing rapidly and compliance is a core gating factor for adoption. MICA and FATF guidelines require documented compliance evidence, including issuer attestations and audit trails. If we can generate consistent compliance reports and an audit log that are easily accessible via API and UI, we unlock concrete business value: faster onboarding of enterprise customers, fewer compliance objections, and improved trust. The dashboard and onboarding experiences in the frontend depend on backend APIs that can reliably provide compliance status, readiness flags, and rationale for those statuses. In turn, this data can drive analytics and product insights around which compliance steps correlate with successful token issuance and conversion.

This issue aligns with the roadmap’s Phase 2 Enterprise Compliance objectives, including jurisdiction tracking, compliance reporting, and regulatory integration readiness. Implementing a robust backend foundation now allows the UI to move ahead in parallel and reduces time to revenue by enabling the sales team to demonstrate compliance evidence in pilots. It also sets the groundwork for future KYC and AML integration, without forcing a redesign of core data models later. The outcome is a platform that can legitimately claim enterprise‑grade compliance capabilities, improving competitive advantage and supporting the long‑term subscription revenue goal.

Product overview

See the business owner roadmap: https://raw.githubusercontent.com/scholtz/biatec-tokens/refs/heads/main/business-owner-roadmap.md

Scope

This issue is scoped to the backend API and data layer for compliance reporting, audit trail export, and jurisdiction‑aware compliance status. It does not require a full UI implementation, but it must deliver stable endpoints and data models that the frontend can consume. The work includes data modeling, service logic, API endpoints, and background jobs where necessary, along with a minimal rules engine for jurisdiction tagging.

In scope capabilities:

  1. Compliance Report API

    • Create endpoints to generate and retrieve compliance reports for a token, issuer, or issuance event. Reports should summarize MICA readiness, attestation presence, audit trail completeness, and a list of compliance checks with pass/fail status and timestamps.
    • Provide machine‑readable JSON report and downloadable CSV/JSON export formats. A report must have a stable schema version for forward compatibility.
  2. Audit Trail Export API

    • Implement an endpoint that returns a normalized audit trail for token issuance, updates, and compliance events. Include event type, actor, timestamp, and associated transaction or attestation IDs.
    • Support pagination and filtering by date range, event type, and token ID. Provide both JSON...

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Add compliance reporting and jurisdiction-aware audit exports Backend: Add jurisdiction-aware compliance reporting with config-driven rules engine Feb 5, 2026
Copilot AI requested a review from ludovit-scholtz February 5, 2026 01:37
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

✅ CI checks passed!

📄 OpenAPI specification generated and available as workflow artifact: openapi-specification

2 similar comments
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

✅ CI checks passed!

📄 OpenAPI specification generated and available as workflow artifact: openapi-specification

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

✅ CI checks passed!

📄 OpenAPI specification generated and available as workflow artifact: openapi-specification

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Test Results

1 231 tests  +22   1 228 ✅ +22   28s ⏱️ -4s
    1 suites ± 0       3 💤 ± 0 
    1 files   ± 0       0 ❌ ± 0 

Results for commit 5f9626e. ± Comparison against base commit f1b2dac.

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

✅ CI checks passed!

📄 OpenAPI specification generated and available as workflow artifact: openapi-specification

1 similar comment
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

✅ CI checks passed!

📄 OpenAPI specification generated and available as workflow artifact: openapi-specification

@ludovit-scholtz ludovit-scholtz marked this pull request as ready for review February 5, 2026 03:16
Copilot AI review requested due to automatic review settings February 5, 2026 03:16
@ludovit-scholtz ludovit-scholtz merged commit 0400862 into master Feb 5, 2026
6 checks passed
@ludovit-scholtz ludovit-scholtz deleted the copilot/add-compliance-reporting-api branch February 5, 2026 03:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a comprehensive jurisdiction-aware compliance reporting system for the Biatec Tokens API. The implementation provides configuration-driven jurisdiction rules, token jurisdiction tagging, compliance evaluation engine, and REST API endpoints with authentication.

Changes:

  • Adds jurisdiction rules management with EU MICA and GLOBAL FATF seeded rules
  • Implements compliance evaluation engine that aggregates multi-jurisdiction requirements
  • Provides 9 REST API endpoints for CRUD operations, evaluation, and token jurisdiction assignments

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
COMPLIANCE_REPORTING_JURISDICTION_IMPLEMENTATION.md Comprehensive implementation documentation covering architecture, components, and deployment
BiatecTokensApi/Models/Compliance/JurisdictionRules.cs Core data models for jurisdiction rules, requirements, and evaluation results
BiatecTokensApi/Repositories/JurisdictionRulesRepository.cs In-memory thread-safe repository with seeded default rules
BiatecTokensApi/Repositories/Interface/IJurisdictionRulesRepository.cs Repository interface defining data access operations
BiatecTokensApi/Services/JurisdictionRulesService.cs Business logic for rule management and compliance evaluation
BiatecTokensApi/Services/Interface/IJurisdictionRulesService.cs Service interface defining business operations
BiatecTokensApi/Controllers/JurisdictionRulesController.cs REST API controller with 9 authenticated endpoints
BiatecTokensApi/Services/ComplianceReportService.cs Enhanced to accept jurisdiction rules service for future integration
BiatecTokensApi/Program.cs Dependency injection registration for new services
BiatecTokensApi/doc/documentation.xml Comprehensive XML documentation for all new APIs
BiatecTokensTests/JurisdictionRulesServiceTests.cs 22 unit tests covering all service operations
BiatecTokensTests/ComplianceReportServiceTests.cs Updated to mock new jurisdiction rules service dependency

private readonly IComplianceReportRepository _reportRepository;
private readonly IEnterpriseAuditService _auditService;
private readonly IComplianceService _complianceService;
private readonly IJurisdictionRulesService _jurisdictionRulesService;
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _jurisdictionRulesService field is injected into the constructor but never used in the service implementation. This creates an unnecessary dependency. Either remove the field and parameter if it's not needed yet, or document that it's reserved for future use. If it's intended for future jurisdiction-aware report generation, consider adding a TODO comment explaining the planned usage.

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +171
var jurisdictions = _tokenJurisdictions.GetOrAdd(key, _ => new List<TokenJurisdiction>());

// If this is marked as primary, unmark other primary jurisdictions
if (tokenJurisdiction.IsPrimary)
{
foreach (var existing in jurisdictions)
{
existing.IsPrimary = false;
}
}

// Remove existing entry for this jurisdiction if present
jurisdictions.RemoveAll(j => j.JurisdictionCode.Equals(tokenJurisdiction.JurisdictionCode, StringComparison.OrdinalIgnoreCase));

tokenJurisdiction.AssignedAt = DateTime.UtcNow;
jurisdictions.Add(tokenJurisdiction);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a potential race condition when modifying the jurisdictions list. The GetOrAdd method returns a reference to the list, but multiple threads could be modifying this list concurrently since List<T> is not thread-safe. Even though the dictionary itself is concurrent, the list within it is not protected. Consider using a lock around the modification operations (lines 159-171) or using a thread-safe collection like ConcurrentBag<TokenJurisdiction> instead of List<TokenJurisdiction>.

Copilot uses AI. Check for mistakes.
Comment on lines +183 to +186
if (_tokenJurisdictions.TryGetValue(key, out var jurisdictions))
{
var removed = jurisdictions.RemoveAll(j =>
j.JurisdictionCode.Equals(jurisdictionCode, StringComparison.OrdinalIgnoreCase)) > 0;
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar race condition exists here. The jurisdictions list retrieved from TryGetValue could be modified by another thread while RemoveAll is executing. This operation should be protected with the same synchronization mechanism used in AssignTokenJurisdictionAsync.

Copilot uses AI. Check for mistakes.
/// ```
///
/// **Access Control:**
/// Returns evaluation only for tokens owned by the authenticated user.
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states "Returns evaluation only for tokens owned by the authenticated user" but there is no ownership verification in the implementation. Any authenticated user can evaluate any token's compliance status. If token ownership verification is required, it should be implemented in the service layer before performing the evaluation. If this is intentional (e.g., compliance information is public), the documentation should be updated to reflect the actual behavior.

Suggested change
/// Returns evaluation only for tokens owned by the authenticated user.
/// Evaluation is performed in the context of the authenticated user address. Any ownership
/// or authorization checks are enforced by the underlying service layer or external policies.

Copilot uses AI. Check for mistakes.
Comment on lines +88 to +89
/// **Access Control:**
/// Requires authenticated user. Admin role recommended for production use.
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation recommends "Admin role recommended for production use" but there is no role-based authorization check in the controller. Any authenticated user can create, update, or delete jurisdiction rules, which could be a security risk. Consider adding role-based authorization with [Authorize(Roles = "Admin")] or a policy-based authorization check if jurisdiction rule management should be restricted to administrators.

Copilot uses AI. Check for mistakes.
Comment on lines +242 to +250
if (result.Success)
{
return Ok(result);
}
else
{
return NotFound(result);
}
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of this 'if' statement return - consider using '?' to express intent better.

Suggested change
if (result.Success)
{
return Ok(result);
}
else
{
return NotFound(result);
}
}
return result.Success ? Ok(result) : NotFound(result);
}

Copilot uses AI. Check for mistakes.
Comment on lines +302 to +311
if (result.Success)
{
return Ok(result);
}
else
{
return result.ErrorMessage?.Contains("not found") == true
? NotFound(result)
: BadRequest(result);
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of this 'if' statement return - consider using '?' to express intent better.

Copilot uses AI. Check for mistakes.
Comment on lines +355 to +362
if (result.Success)
{
return Ok(result);
}
else
{
return NotFound(result);
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of this 'if' statement return - consider using '?' to express intent better.

Suggested change
if (result.Success)
{
return Ok(result);
}
else
{
return NotFound(result);
}
return result.Success ? Ok(result) : NotFound(result);

Copilot uses AI. Check for mistakes.
Comment on lines +523 to +530
if (result.Success)
{
return Ok(result);
}
else
{
return BadRequest(result);
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of this 'if' statement return - consider using '?' to express intent better.

Suggested change
if (result.Success)
{
return Ok(result);
}
else
{
return BadRequest(result);
}
return result.Success ? Ok(result) : BadRequest(result);

Copilot uses AI. Check for mistakes.
Comment on lines +650 to +657
if (result.Success)
{
return Ok(result);
}
else
{
return NotFound(result);
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both branches of this 'if' statement return - consider using '?' to express intent better.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Backend: Compliance reporting & jurisdiction-aware audit exports

2 participants