Migrated core entity primitives (GracePeriod, RegistryLock, TimeOfYear), transfer objects (BaseTransferObject, DomainTransferData, TransferResponse), and HostBase from Joda-Time DateTime to java.time.Instant as Phases 5 and 7.
Migrated the Billing Ecosystem (BillingBase, BillingEvent, BillingRecurrence, BillingCancellation) and associated Beam pipelines (ExpandBillingRecurrencesPipeline, InvoicingPipeline) to java.time.Instant as Phase 6.
Migrated PollMessage event times and all associated Poll flow utilities (PollAckFlow, PollRequestFlow) to use Instant natively.
Migrated core timestamp tracking on EppResource (creationTime, lastEppUpdateTime, deletionTime) as well as CreateAutoTimestamp and UpdateAutoTimestamp to Instant, shedding deprecated DateTime accessors.
Migrated the entire HistoryEntry reporting ecosystem (HistoryEntry, DomainTransactionRecord, HistoryEntryDao) completely to java.time.Instant.
Updated all associated EPP flows, tools, and testing helpers to handle Instants directly where supported.
We add optional Valkey caching of hosts and domains for future use. Eventually, this will allow us to pre-warm large amounts of data in Valkey for quick retrieval during actions like RDAP.
Note: this doesn't actually use the caches yet.
We use Jedis instead of Redisson for speed purposes
(https://www.instaclustr.com/blog/redis-java-clients-and-client-side-caching/)
which means that we have to implement our own multilayer cache but
that's not the worst thing in the world.
Tested on crash with logging and RDAP code that's not included in this
PR -- it behaves as you'd expect, where the local cache works for
immediate re-lookups and the remote cache works after a restart.
Continues the project-wide migration from Joda-Time's DateTime to java.time.Instant, focusing on Trademark Clearinghouse (TMCH), Signed Mark Data (SMD), and Fee extension models.
Key updates:
- TMCH & SMD: Updated SmdRevocationList and domain check/create flows to use Instant for sunrise validations and revocation checks.
- Fee Extension Ecosystem: Refactored FeeCheckRequest, FeeCreateCommandExtension, and BaseFee to use Instant for effective dates and period calculations.
- EPP Objects: Updated DomainInfoData, TransferResponse, and PollMessage objects to use Instant for event timestamps.
- Pricing Logic: DomainPricingLogic methods now accept Instant for cost calculations.
Additionally, DateTimeUtils was enhanced with Instant compatibility methods for plusMonths and minusMonths to safely handle leap years.
Redundant conversions between DateTime and Instant were eliminated throughout the flows and tests. DomainFlowUtils leverages Instant natively to avoid inline casting, and test assertions now utilize Truth's Instant subjects for cleaner validation.
We no longer need this now that all domain contacts have been successfully
removed in sandbox and production, and additionally, we are removing all
contacts entirely soon enough.
This comprehensive refactor continues the migration from Joda-Time to java.time (Instant), focusing on core timestamp models, transition properties, and their integration across the codebase.
Key changes:
- Migrated CreateAutoTimestamp and UpdateAutoTimestamp to use Instant internally, providing Joda-Time bridge methods for backward compatibility.
- Updated TimedTransitionProperty to handle Instant-based transition maps and updated corresponding Hibernate UserTypes (TimedTransitionBaseUserType).
- Migrated GracePeriod, BillingBase, BillingEvent, PollMessage, and PendingActionNotificationResponse fields (e.g., expirationTime, eventTime) to Instant.
- Migrated additional core entities (DomainBase, Registrar, HostBase, LaunchNotice, BsaLabel, DomainTransactionRecord) to use Instant for registrationExpirationTime, lastTransferTime, creationTime, etc.
- Updated Tld and FeatureFlag models to use Instant for claimsPeriodEnd, bsaEnrollStartTime, and status transitions.
- Enhanced CLI tools and parameters (TransitionListParameter, InstantParameter, RequestParameters) to support Instant-based input and output.
- Updated EntityYamlUtils with custom Instant serializers/deserializers to maintain format consistency (e.g., .SSSZ precision) required for YAML-based tests.
- Implemented UtcInstantAdapter to ensure JAXB XML serialization maintains millisecond accuracy, matching legacy Joda-Time behavior.
- Resolved Hibernate 6 type mismatches in JPQL and Native queries by ensuring consistent use of Instant for comparisons.
- Updated GEMINI.md with project-specific engineering standards, including the 'one commit per PR' mandate, full-build validation requirement, and commit message style rules.
- Cleaned up unnecessary @JsonIgnore and @JsonProperty annotations that were previously added to methods with parameters or redundant fields.
- Refactored DateTimeUtils to use strongly-typed overloads and standardized naming (earliestOf, latestOf) while avoiding type erasure clashes.
- Cleaned up fully qualified calls to toDateTime and toInstant by adding static imports across core model and flow files.
- Refactored test suites to use clock.now() (Instant) instead of nowUtc() (DateTime) and removed custom Truth subjects in favor of standard assertions.
We want to make sure that we use the same XML factories no matter what,
so we use "newDefaultFactory" instead of "newFactory" (to avoid picking
up some random thing on the classpath).
This also fixes an exception that occurs if you haven't synced the
internal repo with the public repo.
PR 2930 forbids adding statuses that already exist on a domain.
This PR updates the uniform_rapid_suspension command to conform.
PR 2930 also forbids removing non-existent statuses, but it does
not apply to this command.
Add the Fee-1.0 schema in production, allowing the requests with this
extension to be parsed. This allows us to test this extension before hand.
The announcement of this extension in greeting is controlled by a
feature flag in ProtocolDefinition.java. As long as it is not announced,
we do not expect real customers to use this extension.
I think this may have been introduced as part of Gradle 9? Not sure why
it's not showing up in the remote builds but without this, I can't run
any "devTool" commands.
Note: the fixes were suggested by gemini-cli
Our existing precision is milliseconds so we want to stick with that for
Instants. If we want to increase the precision globally after that we can do so
all in one go post-migration, but for now, it would be a bad thing to have mixed
precision going on just depending on whether a class happens to be migrated yet
or not.
This PR also migrates all existing DateTime.nowUtc() calls to use the Clock
interface, so that when they are migrated they will get the benefit of this
precision-setting as well.
BUG= http://b/496985355
Error-prone introduced many more checks in Java 25. We fixed a few
and suppressed most. A follow-up bug is opened to clean this up.
An ai agent should be able to clean up most of it.
This PR is created with gemini-cli. Summary of experience:
* The good: AI caught most compatibility issues, and with permission,
suppressed them through compiler flags and errorprone options.
It also caught many versio references in scripts.
* Where it didn't shine:
- It did not find and update the target version spec in the custome
VKey annotation processor source file.
- It did not flag eclipse-temurin:21 docker image for upgrade.
- When running into failure, its first instinct is to disable checks
e.g., -Werror instead of fixing them.
We don't need these, so there's no point in adding database load (but we
leave the option to include them in the future). Note that these are,
and were, only ever included for domains so we don't need to worry about
hosts.
java.time has been around since Java 8 and was based on joda DateTime, so this
is an overdue migration. We're migrating specifically to Instant in most places
rather than ZonedDateTime because we were always using DateTimes in UTC to
reference a specific instant, which is exactly what Instants are
for. ZonedDateTime set to UTC may still be useful in some places that are heavy
on date math (especially in tests).
There is a lot more work to be done after this, but I wanted to put together a
manual PR showing my overall approach for how to do the migration that I can
then hopefully follow along with AI to continue making these changes throughout
the codebase. The basic approach is to migrate a small number of methods at a
time, marking the old methods as @Deprecated when possible (not always possible
because of @InlineMe restrictions). This PR doesn't yet migrate any DateTime
fields in the model classes, so that's the one remaining type of refactor to
figure out after this. We won't be changing how any of the data is actually
stored in the database.
BUG= http://b/496985355
Previously we would just use the first one we found. This is a valid
behavior, but we want to change it so that we apply the cheapest default
if multiple are available (this way we avoid having to go back after the
fact and give refunds).
* More Gradle 9 preparations
Fix additional compatibility warnings after upgrading to Gradle 8.14.3
from 8.13.
* More Gradle 9 compatibility fix
More fixes after upgrading Gradle from 8.13 to 8.14.3.
Upgraded the gradle-license-report plugin, and handled config leaking
issues.
Researched using gemini web and manually applied the fixes. Gemini-cli
could not find the right solution.
This ended up being wayyyy more complicated than expected due to
issues with Hibernate, various dependencies having conflicts with the
proto dependency version, and other breaking changes.
Notes:
- Hibernate 7 switches up the user type / converter system and for us,
this means we must be / want to be more explicit with how we convert
and store things. For example, we need to add Postgres types to @Column
definitions.
- Hibernate 7.3 has an issue with generic MappedSuperclasses -- we have
issues with BaseDomainLabelList. I'll investigate that, but for now
let's stick with 7.2.x
- H7 is more strict with annotations and prevents us from storing mapped
superclasses embedded within other objects. This kinda makes sense but
makes the History objects a bit more difficult. We had to add "concrete"
embeddable DomainBase and HostBase objects that we can store/retrieve
from the DB.
- We convert some of the calls to "Query" to "TypedQuery" -- in
Hibernate 8 / JPA 4.0 these will be super-deprecated and we'll need to
shift everything over, so this is necessary.
- You aren't supposed to put callback listeners on embedded entities
(because it can be not obvious what's happening). We don't like that,
so we add our own annotations that are processed recursively for
embedded entities, so we get things like the update / create
timestamps.
- Hibernate doesn't allow for multiple converters to be auto-applied to
the same "type" and it counts all VKey converters as one type.
Unfortunately, this means we have to explicitly mark each one.
- A bunch of other dependency changes were required to keep from having
the proto 3/4 conflict
Previously we omit the fee class in responses if the class is standard.
After a rereading of Section 3.7 of RFC 8748, we determined that the fee
class element should be included in all cases.
Note: the `collison` class now becomes `standard-collision`.
Refactor Gradle scripts to replace usages incompatible with Gradle 9.
PR prepared mostly with gemini-cli, with one issue (project.exec)
researched with gemini web and manually applied.
The actual upgrade to Gradle 9 will be in another PR.
Verified: none of the issues reported in build/reports/problems/problems-report.html
is related to Gradle 9.
PR 2917 added two `get(tld)` methods to ClaimsListDao and
SignedMarkRevocationList so that RST test TLDs can have separate claims
and smdr lists.
RST tests are completed and this functionality is no longer needed. we
are replaceing all invocations of the above to `get()`.
The JDK version of SSL has long supported TLS v1.3 (since version 11) so
fortunately we can use TLS v1.3 regardless if which implementation of
SSL we're using.
We prefer OpenSSL in general so I'm not entirely sure why we were using
the JDK version of SSL on the proxy before, but this should work and be
a good idea regardless.
Tested on alpha by running
```
$ openssl s_client -connect epp.registryalpha.foo:700 -tls1_3 -ciphersuites "TLS_AES_128_GCM_SHA256"
```
Previously we'd get a failure, now it returns the proper cert data.
We should be at least at a "good enough" state after this -- I'm sure
there are many updates we could make that would improve the
documentation but this is definitely much improved from before and
should hopefully be good enough to get people started.
This doesn't update everything -- it leaves out some of the more
complicated changes (architecture, code-structure, configuration,
install, and proxy-setup). Those will require more complete rewrites, so
I'm punting them to a future PR.
The only type of thing that can be transferred now is a domain, so
there's no point in having this abstract class / redirection.
This does not include deletion of the contact-response-related XML
classes; that can come next.
This doesn't remove everything -- there are still other contact-related
objects that we'll need to remove (e.g.
ContactPendingActionNotificationResponse) and simplifications we'll need to make
(e.g. only domains can be transferred now, so all transfer data can move
there instead of being generic)
But this removes the bulk of the remaining contact-related code. We'll
keep around the XML request objects, since it's still nice to route them
to the appropriate (exception-throwing but logging) flow class.
For all flows that use Fee extensions, normalize the fee tags in all
non-prod environments.
For flows that do not use fee extensions but with fee tags in the
header, e.g., HostInfo flows, normalization is not performed.