Skip to content

JWT License Key Validation (Ed25519) #63

@fupelaqu

Description

@fupelaqu

Epic 5: Licensing Infrastructure

User Story

As a server operator,
I want license keys to be cryptographically signed JWTs verified offline,
So that keys cannot be forged and validation requires no network access.

Acceptance Criteria

Given a valid JWT signed with Ed25519 (EdDSA algorithm)
When JwtLicenseManager.validate(jwt) is called
Then the signature is verified against the embedded public key
And a Right(LicenseKey) is returned with the correct tier, features, quotas, and expiresAt

Given a JWT with an invalid or tampered signature
When JwtLicenseManager.validate(jwt) is called
Then a Left(InvalidLicense("Invalid signature")) is returned

Given a valid JWT that has expired (past exp claim)
When JwtLicenseManager.validate(jwt) is called
Then a Left(ExpiredLicense(expiredAt)) is returned

Given Ed25519 public keys bundled in the JAR (licensing/src/main/resources/keys/)
When a JWT with kid header "softclient4es-2026-03" is validated
Then the matching public key is loaded from the keyring

Given a JWT with an unknown kid header
When JwtLicenseManager.validate(jwt) is called
Then a Left(InvalidLicense("Unknown key ID: ...")) is returned

Given a JWT with tier: "pro", features: ["materialized_views", "jdbc_driver", "flight_sql", "federation"], quotas: { max_clusters: 5, max_result_rows: 100000 }
When the JWT is successfully validated
Then licenseType returns LicenseType.Pro
And hasFeature(Feature.Federation) returns true
And quotas.maxClusters returns Some(5)

Given build dependencies
When sbt "licensing/compile" is run
Then Bouncy Castle (bcprov-jdk18on) and nimbus-jose-jwt are available for Ed25519 verification and JWT parsing

Dependencies

  • Feature & Quota Extensions (FR30)

Requirements

  • FR22: License key shall be a JWT signed with Ed25519, verified offline using an embedded public key

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions