<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>xyz.tcheeric</groupId>
    <artifactId>imani-bom</artifactId>
    <version>0.1.111</version>
    <packaging>pom</packaging>
    <name>Imani BOM</name>
    <description>Bill of Materials (BOM) for the Imani platform — centralizes dependency versions across all projects</description>

    <properties>
        <java.version>21</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!-- Imani Platform Versions -->
        <imani-commons.version>0.1.2</imani-commons.version>
        <messaging-contracts.version>0.2.1</messaging-contracts.version>
        <imani-identity.version>0.1.3</imani-identity.version>
        <!-- 0.1.26 realigns wallet-lib's own cashu-voucher pin with the 0.10.0 declared
             below. 0.1.25 was built against 0.8.0, so consumers of this BOM linked
             0.8.0-compiled wallet classes against the 0.10.0 jar. Keep these in step. -->
        <!-- 0.1.33 carries the locked-voucher (P2PK) spend path — NUT-11 witness
             signing as a seam rather than a key, and VoucherResigner — plus the fix
             that lets the voucher ledger sign, and therefore publish, at all. -->
        <!-- 0.1.40 ENCRYPTS THE FLOAT AT REST, and migrates the proofs already in
             an existing one. Without it a gateway stores bearer secrets in the
             clear: the staging float's secret_enc column held readable NUT-10
             JSON that anyone with the volume, a snapshot or a backup could spend
             (imani-gateway-customer#74, #60). Encryption is off unless
             WALLET_PASSPHRASE is set, so adopting this BOM changes nothing until
             a consumer supplies one — but the FIRST start with a passphrase
             rewrites the float, so read the runbook before setting it. -->
        <!-- 0.2.0 closes 19 AppSec findings, 2 Critical: bearer proof secrets were
             logged at INFO in full (the "preview" sliced a string by a byte-array
             length), and a caller-supplied mint URL was unauthenticated SSRF into
             the gateway network whose response fed back into the crypto layer.

             BREAKING FOR LOCAL SETUPS: mint URLs resolving to loopback, link-local
             or RFC-1918 are now refused. docker-compose and integration
             environments point at exactly those, and must set
             -Dwallet.mint.allowInternalAddresses=true. Never set it anywhere
             reachable from outside — that flag is the whole of WALLET-02. -->
        <!-- 0.3.6 fixes a double-spend: two concurrent requests picked the same
             proof, because the aggregate's lock guarded a per-request object.
             Staging managed exactly ONE issuance per concurrent batch whatever
             the concurrency, so two stalls selling at once took each other down.
             Adds wallet migration V7 (reserved_by, reserved_until), so a service
             adopting this runs a schema change on its wallet database. -->
        <!-- 0.3.9 stops the mint circuit breaker counting a rejected proof as a
             mint failure. isProofRejection matched "already_used"/"ALREADY_SPENT",
             which are CashuErrorCode constant names and are not on the wire: the
             mint sends {"detail": "Proof already used", "code": 11001}. So a
             healthy mint refusing a spent proof opened the breaker. Staging saw
             it open five minutes and fail 189 voucher finalisations with zero
             5xx from the mint, which halts issuance entirely and strands paying
             customers at FUNDED. Breaker state is still not exported to
             Prometheus, so it is invisible while it happens: wallet-lib#69. -->
        <imani-wallet.version>0.3.11</imani-wallet.version>
        <!-- 0.7.0 adds claim / settleClaim / releaseClaim to ReceiveEscrowPort,
             which every implementor must provide. Consumers that have not
             written those methods must stay on 0.6.2 rather than picking this
             BOM up by accident: the interface really did change.

             The change was briefly built and installed as another 0.6.2, which
             overwrote the released jar in the local ~/.m2 and broke
             gateway-customer's main branch in code nobody had edited. Hence a
             new number for the new interface. -->
        <!-- 0.8.0 closes 14 AppSec findings. This is the contract library, so the
             break is that declared validation is now enforced: unbounded strings and
             collections on untrusted input, nested DTOs that were never
             cascade-validated, five request DTOs with no constraints at all, and URL
             components with no scheme or host constraint (the enabler half of the
             estate's SSRF findings). A request that a consumer's tests accepted may
             now be a 400 — that is the finding working. Because the gap lived here,
             no consumer ever saw it in its own diff. -->
        <!-- 0.8.1 corrects one of those bounds. The Cashu token ceiling was set to
             8192 characters, which is BELOW the size a real token is: a token carries
             one ~1840-character proof per set bit of the amount, so 1500 sat is seven
             proofs and 12870 characters. Vouchers minted successfully and were then
             refused at POST /api/v1/wallet/receive — the 2026-09-18 failed sells. The
             ceiling moved to 65536 and is still a bound. -->
        <!-- 0.10.0 adds SURFACE rather than changing any: `BtcRateProvider` (the
             fetching half of ExchangeRatePort, so a second rate source can exist
             without touching conversion arithmetic) and `VOUCHER_009`
             (VOUCHER_RATE_UNAVAILABLE). A consumer referencing neither is unaffected.

             gateway-customer 0.12.0 imports both and does NOT compile against 0.9.0,
             so this pin has to move before that release can build. -->
        <!-- 0.10.1 raises MAX_TOKEN_CHARS 65536 -> 262144. The old value was derived
             as "32 proofs", which assumes a keyset whose denominations climb with the
             amount; the live keyset is 1..1024, so proof count scales linearly and a
             EUR 25 sale (33,246 sat) needs 39 proofs. That capped merchants at about
             EUR 18 per sale. The new value is two thirds of the chunked-DM sender
             limit, which is the limit that actually binds. Still a bound, so API-02
             holds and no consumer has to change anything. -->
        <imani-gateway-api.version>0.10.1</imani-gateway-api.version>
        <!-- 0.1.3 makes Nip98AuthFilter authenticate reads, not only writes. Until
             it, the no-Authorization branch rejected write methods only, so every GET
             on a protected prefix passed through unauthenticated on every gateway.
             Consumers that adopt this BOM version also pick up 0.1.1 (CRIT-1 event-id
             binding) and 0.1.2 (HIGH-3 URL binding) — all three gateways were pinning
             0.1.0 locally and had received neither. -->
        <!-- 0.2.0 closes 14 AppSec findings, 2 Critical, and this library is upstream
             of every gateway — so both Criticals were simultaneously true of the whole
             estate. SEC-01: every path-based security decision read the raw
             percent-encoded URI, so %2F and path parameters bypassed every protected
             prefix; 6 of 6 bypass variants were executed against the real filter and
             reached the handler with no Authorization header. SEC-02: X-Forwarded-Host
             is not stripped at the edge, so a captured NIP-98 event authenticated
             against a service it was never issued for.

             ADOPTING THIS REQUIRES CONFIGURATION. A service with no
             gateway.security.nip98.public-base-url now REFUSES TO START; set it to
             that service's own public origin, or set
             gateway.security.nip98.allow-insecure-header-url-binding=true to knowingly
             keep the bypass outside production. Separately, an edge shared secret under
             32 characters now DISABLES NapProxyAuthFilter and logs ERROR rather than
             being silently accepted, so X-Auth-Pubkey stops being honoured: watch for
             nap_proxy_auth_disabled at startup. The symptom otherwise is a service that
             boots, reports healthy, and refuses everyone. -->
        <imani-security.version>0.2.2</imani-security.version>
        <imani-nostrdb.version>0.1.4</imani-nostrdb.version>
        <!-- 0.6.0 is the current release (reposilite <release>0.6.0; published
             0.1.0, 0.1.1, 0.4.0, 0.6.0). It carries the authorization layer —
             AclResolver / PermissionRegistry / RoleDefinition and the
             @RequiresPermission / @RequiresRole / @RequiresSession guards — none
             of which exist in 0.1.0.

             Consumers had been overriding this individually (dalia, bottin) or
             silently running 0.1.0 (gateway-core resolved 0.1.1 only because it
             re-pinned all five artifacts itself). Declaring the real version
             here is what lets them stop.

             0.7.0 adds `supported_extensions` to AuthInitResponse and makes the record
             tolerate unknown fields. The second half is the reason to take it: Jackson
             throws on an unrecognised property by default, so a Java client talking to
             a TypeScript NAP server that advertises extensions failed with
             UnrecognizedPropertyException. Every additive field RFC §24.3 permits was a
             breaking change for this client until that fix. -->
        <!-- 0.9.0 adds NapProperties.allowAllPrincipals, a record component, which is
             a source-breaking change for anyone constructing it directly.
             Consumers must pass it; null defaults to FALSE, the safe direction.

             Moving because the artifact published as 0.8.0 ALREADY carries that
             component while nap-java's master does not, so "0.8.0" means two
             different shapes depending on where it is resolved from. Pinning to a
             version whose meaning is ambiguous is worse than moving to one that is
             not. See tcheeric/nap#41. -->
        <nap-java.version>0.9.0</nap-java.version>
        <imani-merchant.version>0.2.0</imani-merchant.version>

        <!-- Cashu Library Versions -->
        <!-- Completes the P2PK_VOUCHER set that 0.1.60 began. cashu-lib 0.29.0 defines
             the composite NUT-10 kind, cashu-voucher 0.13.0 signs it, and cashu-mint
             0.35.0 enforces the voucher conditions and the P2PK witness together.

             0.1.60 carried only cashu-lib and nap-java because cashu-voucher imports
             this BOM to get its cashu-lib version, so the two could not be released in
             one step. That intermediate state is now closed: pin all three together and
             do not mix a 0.29.0 cashu-lib with a mint older than 0.35.0, which would
             dispatch the kind to a condition that never checks a witness.

             0.1.63 moves all of these for the 2026-09-05 security audit. They are one
             set because the fixes cross the boundaries: cashu-lib 0.30.0 rejects
             off-curve public keys and refuses to downgrade a locked secret to a bearer
             secret, and cashu-voucher 0.14.0 requires a registered issuer key before
             calling a signature valid. A consumer that took the voucher bump without the
             lib bump would verify voucher signatures against keys the library still
             accepts off-curve, so the issuer check would rest on a key type the crypto
             layer no longer trusts. cashu-mint 0.36.0 additionally fixes the audit
             Critical: P2PK proofs were never BDHKE-verified on /v1/swap.

             Note cashu-vault and cashu-wallet were pinned to cashu-lib 0.27.0 and
             cashu-ledger to 0.21.0 before this release, so none of them had received any
             library security fix (audit L-36). All three now build against 0.30.0.

             0.1.87 moves cashu-lib and cashu-voucher as a set for the issuance
             warrant: cashu-lib 0.30.4 carries VoucherTags.ISSUANCE_WARRANT on the
             secret, and cashu-voucher 0.14.3 defines the IssuanceWarrant scheme that
             gives the tag meaning. A consumer taking one without the other either has
             a tag nothing can build or verify, or a verifier with nowhere to read from.

             Both are FRESH coordinates, not re-cuts. 0.1.86 pinned cashu-lib 0.30.3,
             a tag that contains no warrant code, while the code claimed to be the
             already-published 0.30.2; cashu-voucher 0.14.2 was likewise published
             before the warrant was added under it. Local builds hid this because ~/.m2
             held rebuilt jars shadowing the published artefacts of those coordinates.
             Neither 0.30.2/0.30.3 nor 0.14.2 is reused with different bytes. -->
        <cashu-lib.version>0.30.6</cashu-lib.version>
        <cashu-wallet.version>0.8.2</cashu-wallet.version>
        <!-- 0.14.1 stops a non-pubkey `p` tag costing the whole ledger event. A
             relay rejects the ENTIRE event when a `p` tag is not a 32-byte pubkey,
             and it does not tell the writer, so the gateway logged publish_success
             while the ledger stored nothing. -->
        <cashu-voucher.version>0.14.4</cashu-voucher.version>
        <cashu-ledger.version>0.7.3</cashu-ledger.version>
        <!-- The mint and the vault are declared here so a consumer of both cannot pin
             them independently and drift: the vault's hold_id schema (0.11.0) and the
             mint that writes it are one release pair. -->
        <!-- 0.37.2 carries the /v1/keys fan-out fix (cashu-mint#467): an uncached
             keyset read was an O(keys) vault walk, and 20 concurrent cold-cache
             requests produced 20 of them. That walk is what once killed
             imani-vault-jpa with an OutOfMemoryError, taking its acceptor thread with
             it so the vault refused all connections and nothing could mint. A cache
             alone left it aimed at the worst moment: every restart begins cold, and a
             deploy is when every wallet reconnects at once.

             Skips 0.36.6-0.37.1 rather than stepping through them. 0.37.2 is also the
             first 0.37.x whose mint-admin modules exist at that coordinate at all:
             their parent was left at 0.37.0, so the release workflow failed on every
             tag from v0.37.0 and published nothing for them.

             Still vault 0.12.1, so the mint/vault pair below is unchanged. -->
        <!-- 0.38.0 extends the keyset ladder to 1..2^23, which reaches the mint's own
             10,000,000 sat per-operation cap. Below that a greedy split uses the top
             denomination repeatedly, so proof count scaled LINEARLY with the amount:
             a EUR 25.00 sale was 39 proofs rather than 8. Minor because a NEW keyset
             contains 24 denominations rather than 11; existing mints need a rotation
             to pick it up, and archived keysets keep redeeming meanwhile. -->
        <cashu-mint.version>0.38.4</cashu-mint.version>
        <cashu-vault.version>0.13.0</cashu-vault.version>

        <!-- Nostr Java Versions -->
        <nostr-java.version>2.3.1</nostr-java.version>

        <!-- NsecBunker Java Versions -->
        <nsecbunker-java.version>0.2.0</nsecbunker-java.version>

        <!-- Nostrdb JNI Version -->
        <nostrdb-jni.version>0.2.2</nostrdb-jni.version>

        <!-- Spring Boot (imported as BOM) -->
        <spring-boot.version>3.5.16</spring-boot.version>

        <!-- Tomcat, overriding what Spring Boot pins.
             Boot 3.5.16 ships Tomcat 10.1.55, which is NOT enough: 10.1.55
             remains affected by three CRITICALs, including CVE-2026-65905 and
             CVE-2026-43512, both authentication bypasses. 10.1.58 is the first
             release clear of all of them (verified against OSV: 10.1.55, .56
             and .57 all report 3 CRITICAL). 10.1.58 itself was never published
             to Maven Central (the index skips from .57 to .59), so the
             advisories name a version nobody can actually depend on, and the
             real floor is 10.1.59.
             Spring Boot reads this exact property name, so setting it here
             re-versions the whole Tomcat family coherently.
             Remove this override once a Boot release ships >= 10.1.59. -->
        <tomcat.version>10.1.59</tomcat.version>

        <!-- Core Dependencies -->
        <!-- 1.84, not 1.83: CVE-2025-14813 (GOSTCTR) is fixed in 1.80.2,
             1.81.1 and 1.84 only. An open Snyk PR proposed 1.83, which OSV
             reports as carrying MORE vulnerabilities than the 1.81 it replaces
             (3 vs 2), so it would have looked like a fix and left the finding
             in place. -->
        <!-- 1.85 for CVE-2026-8763 (CRITICAL): X.509 Name Constraints can be bypassed
             with a trailing dot in an rfc822Name or URI, so a certificate can assert a
             name the constraint exists to forbid. Both artifacts below take this value,
             which is the point of the single property: the previous BouncyCastle CVE
             stayed live because jdk15to18 arrived transitively at an older version while
             the declared jdk18on was already patched, and the mismatch looked like a fix.

             Surfaced by cashu-mint's SBOM-based scan (398ja/cashu-mint#432). The
             file-based scan it replaced reported zero findings against the same tree. -->
        <bcprov-jdk18on.version>1.85</bcprov-jdk18on.version>
        <commons-lang3.version>3.18.0</commons-lang3.version>
        <commons-text.version>1.12.0</commons-text.version>
        <slf4j.version>2.0.17</slf4j.version>
        <lombok.version>1.18.40</lombok.version>
        <picocli.version>4.7.6</picocli.version>

        <!-- Database -->
        <postgresql.version>42.7.7</postgresql.version>
        <h2.version>2.2.224</h2.version>
        <!-- 7.1.0 for the virtual-thread spin fix in ConcurrentBag.unreserve
             (HikariCP 5e63223, "Avoid virtual-thread yield spin", released in
             7.1.0). Before it, unreserve spins on Thread.yield() while waiters
             exist. Thread.yield() does not deschedule a VIRTUAL thread, so on
             a service with spring.threads.virtual.enabled=true the keepalive
             task pins a carrier core and never leaves.

             Observed on staging 2026-09-24: gateway-customer's
             CashuWalletPool housekeeper burned 359 SECONDS of CPU in 518s of
             uptime, the Tomcat handler pool was starved to zero threads, and
             every request including /actuator/health timed out until the
             container was restarted. Stack was exactly
             Thread.yield -> ConcurrentBag.unreserve -> HikariPool$KeepaliveTask.
             See imani-gateway-customer#106.

             This overrides Spring Boot 3.5.5's managed 6.3.3. The previous
             6.3.2 pin carried no comment and was set once when this bom was
             created, so it was staleness rather than a constraint.
             7.1.0 targets bytecode 55 (JDK 11), so JDK 21 is fine.
             Verified: gateway-customer 728 tests and gateway-core 855 tests
             green on 7.1.0. -->
        <hikaricp.version>7.1.0</hikaricp.version>

        <!-- Resilience -->
        <resilience4j.version>2.1.0</resilience4j.version>

        <!-- Cryptography -->
        <argon2-jvm.version>2.11</argon2-jvm.version>

        <!-- Validation -->
        <jakarta-validation.version>3.1.0</jakarta-validation.version>
        <hibernate-validator.version>8.0.3.Final</hibernate-validator.version>
        <jakarta-el.version>4.0.2</jakarta-el.version>

        <!-- Logging -->
        <!-- Deliberately NOT set: Spring Boot versions logback, and it must
             version BOTH halves of the pair. This pinned logback-classic to
             1.5.18 while leaving logback-core to Boot, which moved to 1.5.34 on
             the 3.5.16 bump; the split pair threw
             NoSuchMethodError: LoggerContext.initCollisionMaps() at every
             Spring context load. A pin that covers one artifact of a
             tightly-coupled pair is worse than no pin.
        <logback.version>1.5.18</logback.version> -->
        <logstash-logback-encoder.version>8.0</logstash-logback-encoder.version>

        <!-- Observability -->
        <opentelemetry.version>1.44.1</opentelemetry.version>
        <opentelemetry-alpha.version>1.44.1-alpha</opentelemetry-alpha.version>
        <opentelemetry-semconv.version>1.30.1-alpha</opentelemetry-semconv.version>
        <micrometer.version>1.14.2</micrometer.version>

        <!-- Testing -->
        <junit.version>5.12.2</junit.version>
        <junit-platform.version>1.12.2</junit-platform.version>
        <assertj.version>3.27.4</assertj.version>
        <mockito.version>5.19.0</mockito.version>
        <byte-buddy.version>1.15.11</byte-buddy.version>
        <testcontainers.version>1.20.4</testcontainers.version>
        <jqwik.version>1.8.0</jqwik.version>
        <wiremock.version>3.9.1</wiremock.version>
        <awaitility.version>4.3.0</awaitility.version>
        <guava.version>33.4.8-jre</guava.version>

        <!-- Jackson. Tracks what Spring Boot ships, and must keep tracking it.
             These were pinned at 2.20.0/2.20, which silently overrode Boot's
             2.21.4 across nine artifacts: a local pin on a BOM-managed
             artifact never fails the build, it just wins. 2.20.0 carries five
             known advisories and 2.21.4 carries three, so the pin was holding
             consumers on the worse version.
             Open Snyk PRs proposing 2.20.1 do not help either: OSV reports the
             same five advisories against it.
             jackson-annotations versions SEPARATELY (2.21, not 2.21.4), as
             jackson-bom's own jackson.version.annotations property shows. -->
        <jackson.version>2.21.5</jackson.version>
        <jackson.annotations.version>2.21</jackson.annotations.version>

        <!-- Build Plugins -->
        <flyway.version>11.7.2</flyway.version>
        <jacoco.version>0.8.10</jacoco.version>
        <maven.surefire.plugin.version>3.5.2</maven.surefire.plugin.version>
        <maven.enforcer.plugin.version>3.4.1</maven.enforcer.plugin.version>
        <maven.shade.plugin.version>3.6.0</maven.shade.plugin.version>
        <maven.failsafe.plugin.version>3.2.5</maven.failsafe.plugin.version>
        <maven.jar.plugin.version>3.3.0</maven.jar.plugin.version>
        <jib-maven-plugin.version>3.4.6</jib-maven-plugin.version>

        <!-- Other -->
        <bip-utils.version>2.0.0</bip-utils.version>
        <expressly.version>5.0.0</expressly.version>
        <commons-logging.version>1.3.5</commons-logging.version>
        <undertow.version>2.3.18.Final</undertow.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Tomcat, pinned AHEAD of the Spring Boot import below.
                 Order is load-bearing: an imported BOM cannot be overridden by
                 a property here, because spring-boot-dependencies resolves
                 ${tomcat.version} against its OWN properties, not ours. The
                 only thing that wins is an explicit entry declared BEFORE the
                 import, since Maven takes the first declaration it sees.
                 Setting the property alone looks right and does nothing: it was
                 verified failing, resolving 10.1.55 in gateway-core.
                 Boot 3.5.16 ships 10.1.55, which is still affected by three
                 CRITICALs including two authentication bypasses. 10.1.59 is
                 the first PUBLISHED release clear of them: the advisories say
                 10.1.58, but that version was never pushed to Central. -->
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-core</artifactId>
                <version>${tomcat.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-el</artifactId>
                <version>${tomcat.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-websocket</artifactId>
                <version>${tomcat.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-annotations-api</artifactId>
                <version>${tomcat.version}</version>
            </dependency>

            <!-- Spring Boot BOM -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- JUnit BOM -->
            <dependency>
                <groupId>org.junit</groupId>
                <artifactId>junit-bom</artifactId>
                <version>${junit.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- OpenTelemetry BOM -->
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-bom</artifactId>
                <version>${opentelemetry.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Micrometer BOM -->
            <dependency>
                <groupId>io.micrometer</groupId>
                <artifactId>micrometer-bom</artifactId>
                <version>${micrometer.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Testcontainers BOM -->
            <dependency>
                <groupId>org.testcontainers</groupId>
                <artifactId>testcontainers-bom</artifactId>
                <version>${testcontainers.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- ============================================================ -->
            <!-- Imani Platform Artifacts                                      -->
            <!-- ============================================================ -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>imani-commons</artifactId>
                <version>${imani-commons.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>messaging-contracts</artifactId>
                <version>${messaging-contracts.version}</version>
            </dependency>

            <!-- Identity Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>identity-domain</artifactId>
                <version>${imani-identity.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>identity-api</artifactId>
                <version>${imani-identity.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>identity-application</artifactId>
                <version>${imani-identity.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>identity-infrastructure</artifactId>
                <version>${imani-identity.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>identity-storage-file</artifactId>
                <version>${imani-identity.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>identity-cli</artifactId>
                <version>${imani-identity.version}</version>
            </dependency>

            <!-- Wallet Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-core-base</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-core-observability</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-core-cashu</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-core-nostr</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-core-app</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-nip-04</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-nip-17</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-nip-42</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-nip-44</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>wallet-nip-60</artifactId>
                <version>${imani-wallet.version}</version>
            </dependency>

            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>imani-gateway-api</artifactId>
                <version>${imani-gateway-api.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>imani-security</artifactId>
                <version>${imani-security.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>imani-nostrdb</artifactId>
                <version>${imani-nostrdb.version}</version>
            </dependency>

            <!-- Merchant Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>merchant-domain</artifactId>
                <version>${imani-merchant.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>merchant-api</artifactId>
                <version>${imani-merchant.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>merchant-application</artifactId>
                <version>${imani-merchant.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>merchant-infrastructure</artifactId>
                <version>${imani-merchant.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>merchant-rest</artifactId>
                <version>${imani-merchant.version}</version>
            </dependency>

            <!-- NAP Java Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nap-core</artifactId>
                <version>${nap-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nap-server</artifactId>
                <version>${nap-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nap-jdbc</artifactId>
                <version>${nap-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nap-client</artifactId>
                <version>${nap-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nap-spring</artifactId>
                <version>${nap-java.version}</version>
            </dependency>

            <!-- ============================================================ -->
            <!-- Cashu Library Modules                                         -->
            <!-- ============================================================ -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-lib-entities</artifactId>
                <version>${cashu-lib.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-lib-crypto</artifactId>
                <version>${cashu-lib.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-lib-common</artifactId>
                <version>${cashu-lib.version}</version>
            </dependency>

            <!-- Cashu Wallet Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-wallet-protocol</artifactId>
                <version>${cashu-wallet.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-wallet-client</artifactId>
                <version>${cashu-wallet.version}</version>
            </dependency>

            <!-- Cashu Vault Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-vault-api</artifactId>
                <version>${cashu-vault.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-vault-jpa</artifactId>
                <version>${cashu-vault.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-vault-hashi</artifactId>
                <version>${cashu-vault.version}</version>
            </dependency>

            <!-- Cashu Mint Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-mint-protocol</artifactId>
                <version>${cashu-mint.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-mint-rest</artifactId>
                <version>${cashu-mint.version}</version>
            </dependency>

            <!-- Cashu Voucher Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-voucher-domain</artifactId>
                <version>${cashu-voucher.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-voucher-app</artifactId>
                <version>${cashu-voucher.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-voucher-nostr</artifactId>
                <version>${cashu-voucher.version}</version>
            </dependency>
            <!--
              New in cashu-voucher 0.10.0. Managed here for consistency with its three
              siblings; nothing depends on it yet. It is a pure SignedVoucher -> pass.json
              mapper (schema only — no certificates, no .pkpass container, no pass update
              web service), so adding it to the BOM commits no one to Apple Wallet.
            -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-voucher-pass</artifactId>
                <version>${cashu-voucher.version}</version>
            </dependency>

            <!-- Cashu Ledger Modules (spec 048 trace-event producer SDK) -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-ledger-trace-publisher</artifactId>
                <version>${cashu-ledger.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>cashu-ledger-trace-core</artifactId>
                <version>${cashu-ledger.version}</version>
            </dependency>

            <!-- ============================================================ -->
            <!-- Nostr Java 2.0 Modules                                        -->
            <!-- ============================================================ -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nostr-java-core</artifactId>
                <version>${nostr-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nostr-java-event</artifactId>
                <version>${nostr-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nostr-java-identity</artifactId>
                <version>${nostr-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nostr-java-client</artifactId>
                <version>${nostr-java.version}</version>
            </dependency>

            <!-- NsecBunker Java Modules -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nsecbunker-core</artifactId>
                <version>${nsecbunker-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nsecbunker-connection</artifactId>
                <version>${nsecbunker-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nsecbunker-protocol</artifactId>
                <version>${nsecbunker-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nsecbunker-admin</artifactId>
                <version>${nsecbunker-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nsecbunker-client</artifactId>
                <version>${nsecbunker-java.version}</version>
            </dependency>
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nsecbunker-account</artifactId>
                <version>${nsecbunker-java.version}</version>
            </dependency>

            <!-- Nostrdb JNI -->
            <dependency>
                <groupId>xyz.tcheeric</groupId>
                <artifactId>nostrdb-jni</artifactId>
                <version>${nostrdb-jni.version}</version>
            </dependency>

            <!-- ============================================================ -->
            <!-- Jackson (pinned to 2.20.0 for TokenV4 compatibility)          -->
            <!-- ============================================================ -->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>${jackson.annotations.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-jsr310</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.datatype</groupId>
                <artifactId>jackson-datatype-jdk8</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-cbor</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-toml</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.module</groupId>
                <artifactId>jackson-module-parameter-names</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.module</groupId>
                <artifactId>jackson-module-blackbird</artifactId>
                <version>${jackson.version}</version>
            </dependency>

            <!-- ============================================================ -->
            <!-- Core Dependencies                                             -->
            <!-- ============================================================ -->
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk18on</artifactId>
                <version>${bcprov-jdk18on.version}</version>
            </dependency>
            <!-- The same provider built for an older JDK. Nothing declares it,
                 but it arrives transitively through bip-utils -> bitcoinj-core
                 at 1.80, which CVE-2025-14813 affects just as it does jdk18on.
                 Managed at the same version so the two cannot drift: a
                 vulnerable crypto provider reaching the classpath by a path
                 nobody reads is precisely the case a BOM exists to close.
                 Measured in imani-wallet-lib, which resolved 1.80 while its
                 declared jdk18on was already 1.84. -->
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk15to18</artifactId>
                <version>${bcprov-jdk18on.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-text</artifactId>
                <version>${commons-text.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>info.picocli</groupId>
                <artifactId>picocli</artifactId>
                <version>${picocli.version}</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>${commons-logging.version}</version>
            </dependency>

            <!-- Database -->
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <version>${postgresql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <version>${h2.version}</version>
            </dependency>
            <dependency>
                <groupId>com.zaxxer</groupId>
                <artifactId>HikariCP</artifactId>
                <version>${hikaricp.version}</version>
            </dependency>
            <dependency>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-core</artifactId>
                <version>${flyway.version}</version>
            </dependency>
            <dependency>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-database-postgresql</artifactId>
                <version>${flyway.version}</version>
            </dependency>

            <!-- Resilience -->
            <dependency>
                <groupId>io.github.resilience4j</groupId>
                <artifactId>resilience4j-retry</artifactId>
                <version>${resilience4j.version}</version>
            </dependency>
            <dependency>
                <groupId>io.github.resilience4j</groupId>
                <artifactId>resilience4j-circuitbreaker</artifactId>
                <version>${resilience4j.version}</version>
            </dependency>
            <dependency>
                <groupId>io.github.resilience4j</groupId>
                <artifactId>resilience4j-ratelimiter</artifactId>
                <version>${resilience4j.version}</version>
            </dependency>

            <!-- Cryptography -->
            <dependency>
                <groupId>de.mkammerer</groupId>
                <artifactId>argon2-jvm</artifactId>
                <version>${argon2-jvm.version}</version>
            </dependency>

            <!-- Validation -->
            <dependency>
                <groupId>jakarta.validation</groupId>
                <artifactId>jakarta.validation-api</artifactId>
                <version>${jakarta-validation.version}</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>${hibernate-validator.version}</version>
            </dependency>
            <dependency>
                <groupId>org.glassfish</groupId>
                <artifactId>jakarta.el</artifactId>
                <version>${jakarta-el.version}</version>
            </dependency>

            <!-- Logging. logback-classic/-core are versioned by the Spring
                 Boot import, together; see the logback.version note above. -->
            <dependency>
                <groupId>net.logstash.logback</groupId>
                <artifactId>logstash-logback-encoder</artifactId>
                <version>${logstash-logback-encoder.version}</version>
            </dependency>

            <!-- Testing -->
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-engine</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-api</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-commons</artifactId>
                <version>${junit-platform.version}</version>
            </dependency>
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-engine</artifactId>
                <version>${junit-platform.version}</version>
            </dependency>
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-launcher</artifactId>
                <version>${junit-platform.version}</version>
            </dependency>
            <dependency>
                <groupId>org.assertj</groupId>
                <artifactId>assertj-core</artifactId>
                <version>${assertj.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>${mockito.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-junit-jupiter</artifactId>
                <version>${mockito.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy</artifactId>
                <version>${byte-buddy.version}</version>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy-agent</artifactId>
                <version>${byte-buddy.version}</version>
            </dependency>
            <dependency>
                <groupId>net.jqwik</groupId>
                <artifactId>jqwik</artifactId>
                <version>${jqwik.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wiremock</groupId>
                <artifactId>wiremock</artifactId>
                <version>${wiremock.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.awaitility</groupId>
                <artifactId>awaitility</artifactId>
                <version>${awaitility.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>${guava.version}</version>
                <scope>test</scope>
            </dependency>

            <!-- Other -->
            <dependency>
                <groupId>io.undertow</groupId>
                <artifactId>undertow-core</artifactId>
                <version>${undertow.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.13.0</version>
                    <configuration>
                        <parameters>true</parameters>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${maven.surefire.plugin.version}</version>
                    <configuration>
                        <useModulePath>false</useModulePath>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>${jacoco.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>${maven.failsafe.plugin.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <distributionManagement>
        <repository>
            <id>reposilite-releases</id>
            <url>https://maven.398ja.xyz/releases</url>
        </repository>
        <snapshotRepository>
            <id>reposilite-snapshots</id>
            <url>https://maven.398ja.xyz/snapshots</url>
        </snapshotRepository>
    </distributionManagement>

    <repositories>
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <releases><enabled>true</enabled></releases>
            <snapshots><enabled>false</enabled></snapshots>
        </repository>
        <repository>
            <id>reposilite-releases</id>
            <url>https://maven.398ja.xyz/releases</url>
        </repository>
        <repository>
            <id>reposilite-snapshots</id>
            <url>https://maven.398ja.xyz/snapshots</url>
        </repository>
    </repositories>

</project>
