Brand-aligned reverse-DNS: io.cameleer matches the owned cameleer.io
domain. Part of institutionalization prep — clean break, no compat shims.
Scope:
- 613 .java files: package + import declarations and directory layout
- 5 POMs: groupId for cameleer-server-parent and 4 modules; mainClass FQN
in cameleer-license-minter; internal inter-module dep coordinates
- .claude/rules/{core,app}-classes.md + CLAUDE.md: keep class/API maps in
sync per the maintenance rule in CLAUDE.md
Out of scope (intentionally preserved on com.cameleer):
- com.cameleer:cameleer-common — external dep from the agent repo
- Spring config namespaces (cameleer.server.*) — they're property keys,
not Java packages
Consumer heads-up:
- cameleer-saas pulls io.cameleer:cameleer-license-{api,minter} on next
sync; their POMs need the matching groupId bump.
Verification: mvn install -DskipITs (273 server-app unit tests pass under
io.cameleer.* package names; license-api / server-core / license-minter
modules all green). The repackage step's JAR-rename failure during the run
was a file lock from a co-running dev server, unrelated to the rename.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Splits the pure license contract types (LicenseInfo, LicenseValidator,
LicenseState, LicenseStateMachine, LicenseLimits, DefaultTierLimits) into a
new cameleer-license-api module under package com.cameleer.license.
Why: cameleer-license-minter previously depended on cameleer-server-core for
these types, dragging cameleer-server-core + cameleer-common onto the
classpath of every minter consumer (notably cameleer-saas). The SaaS
management plane has no business carrying server-runtime types — it only
needs the license contract to mint and verify tokens.
After:
cameleer-license-minter -> cameleer-license-api (no server internals)
cameleer-server-core -> cameleer-license-api
cameleer-saas -> cameleer-license-minter -> cameleer-license-api
Verified: mvn -pl cameleer-license-minter dependency:tree shows the minter
no longer pulls cameleer-server-core or cameleer-common. Full reactor
verify (-DskipITs) green: 371 tests pass.
LicenseGate stays in server-core (server-runtime state holder, not contract).
Closescameleer/cameleer-server#156
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds --verify (requires --public-key) to LicenseMinterCli. After
writing the output file the CLI parses the freshly-minted token
through LicenseValidator against the supplied public key. On
verify failure the output file is deleted (so the bad token is
not accidentally shipped) and the CLI exits 3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reads PEM or base64 PKCS#8 Ed25519 private key, maps --max-foo-bar
flags to max_foo_bar limit keys, parses --expires as a UTC date,
defaults --grace-days to 0. Unknown flags fail fast with exit 2.
--verify path is added in the next task.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure signing primitive: serialises LicenseInfo to canonical JSON
(sorted top-level keys via ORDER_MAP_ENTRIES_BY_KEYS plus a TreeMap
for the limits sub-object) then signs with Ed25519. Round-trips
through LicenseValidator and is byte-stable across runs for
identical inputs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>