Partner Service
Service Type: Core REST Microservice Language: Kotlin / Micronaut Framework Database: PostgreSQL (owned) Status: Implemented (v0.1)
Overview
Partner Service is the authoritative owner of partner data and lifecycle management within DEUSS. It manages three partner roles (BROKER, PSP, GUARANTOR) and provides individualized platform fee schedules for brokers. The service operates entirely synchronously via REST without asynchronous messaging.
Business Responsibilities
- Partner Lifecycle Management — Onboarding, status transitions (DRAFT → REVIEW_REQUESTED → ACTIVE), deletion (DRAFT only)
- Role & Profile Management — BROKER, PSP, GUARANTOR roles with role-specific details (EBSI credentials, certificates)
- Platform Fee Schedules — Versioned fee structures for brokers (DRAFT/ACTIVE/ARCHIVED states)
- Fee Quote Calculation — Compute concrete fees based on fee type, issuance size, issuer track record
- Audit Logging — Status change history with actor, timestamp, and reason
Owned Data
Entities:
partners— Core partner records (legal name, contact, country, identifiers, IBAN, status)broker_details,psp_details,guarantor_details— Role-specific profilespartner_certificates— Certificates with serial numberspartner_status_history— Audit trail of status transitionspartner_platform_fee_schedules— Versioned fee schedules (DRAFT/ACTIVE/ARCHIVED)partner_platform_fee_schedule_items— Individual fee rules with calculation logicplatform_fee_schedule_templates— Default templates for broker onboarding Constraints:- At most ONE ACTIVE and ONE DRAFT fee schedule per broker at any time
- At most ONE ACTIVE default fee schedule template system-wide
- Unique:
legal_name,contact_email,business_id,legal_entity_id
Inbound Interfaces
REST API
Authentication: JWT Bearer token required; all operations require ADMIN role
Partners Management (/v1/partners)
| Endpoint | Method | Operation | Purpose |
|---|---|---|---|
/v1/partners | POST | createPartner | Create new partner (starts in DRAFT) |
/v1/partners | GET | listPartners | List with filters (name, email, business ID, country, role, status) |
/v1/partners/{partner_id} | GET | getPartner | Fetch partner details |
/v1/partners/{partner_id} | PATCH | updatePartner | Update attributes (not status) |
/v1/partners/{partner_id} | DELETE | deletePartner | Delete (DRAFT only) |
/v1/partners/{partner_id}/status | PATCH | setPartnerStatus | Change status with reason & audit log |
Platform Fee Schedules (/v1/partners/{partner_id}/platform-fee-schedules)
| Endpoint | Method | Operation | Purpose |
|---|---|---|---|
/current | GET | getCurrentPlatformFeeSchedule | Get active fee schedule |
/{fee_schedule_id} | GET | getPlatformFeeSchedule | Get specific version |
/ | POST | createPlatformFeeScheduleDraft | Create draft (copies current active) |
/{fee_schedule_id} | PATCH | updatePlatformFeeSchedule | Update draft items |
/{fee_schedule_id}/publish | POST | publishPlatformFeeSchedule | Publish draft as new active, archive old |
Fee Quotes
| Endpoint | Method | Operation | Purpose |
|---|---|---|---|
/v1/partners/{partner_id}/platform-fee-quote | POST | quotePlatformFee | Calculate concrete fee for broker |
Outbound Interfaces
- Database Only — PostgreSQL direct access via Hibernate/JPA
- No External Service Calls — Partner Service operates independently
- No Kafka/Async Messaging — Synchronous model only
Kafka Integration
Status: Not integrated
- No Kafka producers
- No Kafka consumers
- No CDC/Debezium enabled
External Integrations
- EBSI (Future) —
brokerDetails.ebsiVerifiableCredentialstores EBSI credentials; not actively used - EOA Keys (Future) —
brokerDetails.eoaPublicKeyfor blockchain interactions; stored but not used
Key Business Rules
- Partners must have ≥1 role (BROKER | PSP | GUARANTOR)
- Brokers automatically receive ACTIVE fee schedule copied from default template at onboarding
- Deletion only allowed in DRAFT status
- Fee Schedules:
- Brokers always have exactly 1 ACTIVE schedule + max 1 DRAFT
- Versions increment on each publication
- Items matched hierarchically: (feeType + issuanceSize + issuerTrackRecord) → (feeType + issuanceSize) → (feeType + issuerTrackRecord) → (feeType only)
- Fee Calculation: FIXED amounts or PERCENTAGE of base price, with optional min/max bounds
- Concurrency: Draft creation uses pessimistic lock on active schedule to prevent race conditions
Deployment
Runtime Stack:
- Java 25 (OpenJDK JRE in Alpine container)
- Micronaut on Netty
- PostgreSQL database
- Flyway for schema migrations Configuration:
- Port: 8080
- Health check:
/health(standard Micronaut) - Environment variables:
DATABASE_URL,DATABASE_USER,DATABASE_PASSWORD - Access logging: Enabled Container:
- Non-root user (
runtime) for security - Init process (
tini) for signal handling - JVM container support enabled (
-XX:+UseContainerSupport)
Observability
- Structured Logging: Semantic logging with events and parameters via
DeussLogger - Access Logs: Enabled on Netty
- Health Endpoint: Micronaut standard
/health - Metrics: Unknown (Micrometer integration status not verified)
Technical Notes
- No Async Model — Only REST. Changes to partners don't propagate via events; dependent services must poll or call synchronously.
- Pessimistic Concurrency Control — Draft creation locks the active schedule row to prevent concurrent draft race conditions.
- Validation as Data — Errors returned as
ValidationResult<Error, Success>, not exceptions; enables cleaner control flow. - Semantic Versioning — Fee schedule versions increment per publish; maintains full history.
- Default Template Pattern — New brokers copy from the single ACTIVE system template to ensure consistency.
Relationships with Other Services
- Registry Service — Likely queries Partner Service for broker/partner details during credential verification
- Core Payment Service — May query fee schedules for pricing calculations (Unknown—not verified)
- Indexer (GraphQL) — May expose partner data via GraphQL (Unknown—not verified)
Documentation Sources:
- Source:
core/partner-service/src/ - Migrations:
core/partner-service/src/main/resources/db/migration/ - OpenAPI:
api-specifications/src/main/resources/core/partner-service/public/ - Config:
core/partner-service/src/main/resources/application.yaml - Container:
core/partner-service/Dockerfile