1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

...

40 Commits

Author SHA1 Message Date
gbrodman
14376953e5 Skip EPP params for BRDA (#3083)
this is an extra field that shouldn't be included in this output
apparently
2026-06-05 20:52:54 +00:00
Juan Celhay
c13c9b53e3 Add sandbox to the Cloud Deploy delivery pipeline (#3080)
* add sandbox target to the delivery pipeline

* add sandbox target
2026-06-05 19:32:28 +00:00
Ben McIlwain
1cd6026151 Fix npx build overriding Angular output paths (#3082)
This commit reverts changes from PR #3068 that swapped 'npm run build' for 'npx ng build' while attempting to dynamically set the '--output-path' via the CLI.

Passing '--output-path' on the command line overrides the entire 'outputPath' configuration object in angular.json. Because the new Angular 18 Application Builder (esbuild) nests outputs inside a 'browser/' directory by default, overriding the configuration bypassed the 'browser: ""' flattening property, causing all client assets to be nested deeper than expected.

This resulted in empty deployments because downstream tasks (like Jetty's copyConsole and the deployment tar scripts) expected the assets to be completely flat. By removing the '--output-path' override from the 'npx ng build' calls, the Angular CLI once again respects angular.json, flattens the output into 'staged/dist/', and the restored 'doLast' block successfully copies the artifacts where they belong.
2026-06-05 16:31:14 +00:00
Ben McIlwain
75524fd403 Restore default builds and fix Kokoro tests (#3081)
This commit reverts changes from 5599a0eb3d and most of 5286b1a0dc (PR #3068) that stripped essential dependencies (buildConsoleForAll, buildNomulusImage, buildToolImage, fragileTest) from the default './gradlew build' target, which broke downstream deployment pipelines. It restores the default build to correctly generate all necessary production artifacts and Docker images.

It introduces a new 'fastBuild' target designed explicitly for local developers and CI checks. This lightweight target disables the execution of heavy Docker image builds, Angular compilations, and fragile tests to provide rapid feedback. Sequential execution constraints for parallel Angular builds are maintained to prevent cache corruption.

It updates the ':core:generateSqlSchema' task to execute using the 'unittest' environment instead of 'alpha'. The 'alpha' configuration is a private, internal environment config that is not distributed in the open-source repository, which caused the task to fail for public contributors. By switching to 'unittest', the generator can successfully run using the public test configuration. With this fixed, it also includes the newly generated 'db-schema.sql.generated' file, which now correctly tracks the 'FORBID_INSECURE_ALGORITHMS_RFC_9904' feature flag that was recently added.

Finally, it implements a split-runner execution strategy for the 'sqlIntegrationTest' task to permanently resolve 'failed to discover tests' and 'NoSuchMethodError' exceptions on Kokoro. Because Kokoro tests cross-version compatibility against both legacy deployed artifacts (compiled with JUnit 4 @RunWith wrappers) and modern artifacts (compiled with JUnit 5 @Suite annotations), we cannot statically configure a single test runner. We now dynamically run both the legacy 'useJUnit()' and modern 'useJUnitPlatform()' runners sequentially with 'failOnNoDiscoveredTests' disabled, allowing the appropriate engine to discover and execute the suite without causing classpath collisions.
2026-06-04 15:38:03 +00:00
gbrodman
a5b280838c Remove usages of json-simple (#3060)
We should use gson wherever possible. There's no point in having
unnecessary dependencies (we'll need to keep around jackson for YAML
parsing).
2026-06-01 20:16:32 +00:00
Ben McIlwain
5599a0eb3d Add buildAll task and fix fragile builds (#3077)
This commit adds the buildAll task to restore the existence of a target that builds everything, which was unintentionally removed when the default build was stripped down in PR #3068. It also introduces necessary sequential constraints to the console-webapp build tasks to prevent parallel execution from corrupting the Angular CLI cache. Finally, it addresses paths for the newer Angular esbuild output and hardens the style injection in ConsoleScreenshotTest to prevent fragile test failures.
2026-06-01 19:11:05 +00:00
gbrodman
dde41078cd Forbid SHA-1 digests as part of RFC 9904 changes (#3069)
We can't change digest types that are already in the database but that's
fine (since we just store them as integers). But we forbid them as part
of domain creates/updates.
2026-06-01 17:59:19 +00:00
Ben McIlwain
0030645b1a Harden XML parsing, serialization, and randomness (#3075)
This commit introduces several security hardening improvements across the codebase:
1. XML Processing: Hardened `TransformerFactory` and `SchemaFactory` instantiations in `EppMessage.java` by explicitly enabling `XMLConstants.FEATURE_SECURE_PROCESSING` and disabling external schema access.
2. Randomness: Replaced instances of `java.util.Random` with `java.security.SecureRandom` in `SelfSignedCaCertificate.java` for stronger entropy. (Added documentation in `ProxyModule.java` explaining why `java.util.Random` is intentionally retained there for metrics sampling).
3. Deserialization: Hardened `SerializeUtils.java` by injecting an `ObjectInputFilter` into the `ObjectInputStream`, restricting deserialization strictly to expected `google.registry` classes and standard Java collections.
2026-06-01 14:25:42 +00:00
Ben McIlwain
c5abd2a7c9 Uncap most remaining dependencies (#3073)
This commit relaxes the upper bounds on several dependencies that were previously hardcapped to specific versions:
- com.google.protobuf to [3.25.5,) and [3.17.3,)
- org.apache.beam to [2.72.0,)
- io.github.ss-bhatt to [1.0.0,)
- io.protostuff to [1.8.0,)
- redis.clients:jedis to [7.4.1,)
- org.junit.jupiter and org.junit.platform to [5.6.2,) and [1.6.2,)
- org.jcommander to [2.0,)
- org.jline to [3.0,)
- jakarta.servlet to [6.0,)

Upgrading to the modern versions of jline introduced a breaking change where DefaultParser().parse(line, line.length()) strips trailing spaces when using the default ParseContext.UNSPECIFIED. This caused the autocompletion to misbehave and tests to fail. This commit fixes ShellCommandTest.java by explicitly passing ParseContext.COMPLETE when parsing test strings to perfectly mimic the real-world JLine completion context.

Additionally, SqlIntegrationTestSuite was migrated to JUnit 5's @Suite annotation, fixing a NoClassDefFoundError introduced by uncapping the JUnit Platform dependencies, and the test suite was re-integrated into the standard :build lifecycle.

The following dependencies remain explicitly capped:
1. Hibernate & Jakarta Persistence (Blocked by -Werror):
   These are held back because newer Jakarta Persistence versions deprecate executeUpdate(), setMaxResults(), and getResultStream() on Query.
   - org.hibernate.orm:hibernate-core:7.3.4.Final
   - org.hibernate.orm:hibernate-hikaricp:7.3.4.Final
   - org.hibernate.orm:hibernate-ant:7.3.4.Final
   - jakarta.persistence:jakarta.persistence-api:[3.2.0,4.0.0)

2. Netty (Blocked by abandoned v5):
   Netty 5.0.0 was an experimental release abandoned in 2015. We explicitly cap beneath 5.0.0 so Gradle doesn't resolve dead-end alphas.
   - io.netty:netty-codec-http:[4.1.59.Final, 5.0.0)!!
   - io.netty:netty-codec:[4.1.59.Final, 5.0.0)!!
   - io.netty:netty-common:[4.1.59.Final, 5.0.0)!!
   - io.netty:netty-handler:[4.1.59.Final, 5.0.0)!!
   - io.netty:netty-transport:[4.1.59.Final, 5.0.0)!!
   - io.netty:netty-buffer:[4.1.59.Final, 5.0.0)!!

3. Google API Services:
   Capped beneath their respective unstable beta/v1b4 versions:
   - com.google.apis:google-api-services-dataflow:[v1b3-rev20240430-2.0.0, v1b4)!!
   - com.google.apis:google-api-services-dns:[v1-rev20240419-2.0.0, v2beta)

The lockfiles have been fully regenerated and all test suites ran successfully against the latest available transitive versions.
2026-05-30 02:33:02 +00:00
Ben McIlwain
5286b1a0dc Optimize build and fix fragile tests (#3068)
This commit dramatically optimizes the local Gradle build time, shaving over 5 minutes off a full build execution:
- Instrumented the build to identify fragileTest taking > 3 minutes.
- Refactored TestServer.java to dynamically bind to ephemeral port 0, resolving race conditions.
- Updated UploadBsaUnavailableDomainsActionTest to use the thread-safe TestServer, allowing it to run in parallel.
- Removed outdated exclusions for HostInfoFlowTest and RegistryPipelineWorkerInitializerTest.
- Moved these tests to the highly parallelized standardTest suite.
- Removed the redundant sqlIntegrationTest execution from the standard test phase.
- Stripped heavy Docker (buildNomulusImage) and 5x frontend (buildConsoleForAll) staging dependencies from the standard build task, ensuring they are only run when explicitly deployed.
2026-05-29 02:29:20 +00:00
Ben McIlwain
cd65a4c9d8 Apply continuous self-improvement to skills (#3072)
- pr-polisher: Relaxed the package-lock.json strictness. If package.json or dependencies.gradle are modified, changes to package-lock.json now correctly trigger a WARNING rather than a fatal ERROR, streamlining intentional dependency updates.
- java-ast-refactoring: Replaced the reliance on a local google-java-format binary with the project's native ./gradlew javaIncrementalFormatApply task for post-AST format fixes.
- Updated GEMINI.md and skill instructions to explicitly authorize and mandate the agent to proactively propose systemic infrastructure fixes to the user when it encounters recurring friction, false positives, or brittle workarounds.
- Overhauled the PR polisher "When to Use" instructions in GEMINI.md and SKILL.md into a critical mandate explicitly tying the execution of the polisher to the action of making or amending a commit to prevent agent forgetfulness.
2026-05-28 22:32:18 +00:00
Ben McIlwain
beb7fcc16e Update dependencies and improve workflow docs (#3071)
- Relaxed Google Cloud and gRPC upper bounds to dynamic versions in dependencies.gradle.
- Relaxed JUnit testing framework bounds to < 6.0.0 and < 2.0.0.
- Aligned beam-runners-core-construction-java to 2.72.0!!
- Regenerated all gradle lockfiles across the project.
- Updated GEMINI.md and MEMORY.md with the optimized lockfile/dependency update workflow.
- Fixed presubmit errors in check_diff.py (added Apache 2.0 license header and fixed syntax).
2026-05-28 21:45:43 +00:00
Ben McIlwain
d68f3e5cc0 Centralize Fee validation and add tests (#3070)
This commit:
- Centralizes all creation validation checks into Fee.create().
- Inlines the redundant private createWithCustomDescription() method.
- Removes the awkward ternary operator for null type evaluation.
- Adds FeeTest.java to completely cover the Fee instance creation logic.
2026-05-28 20:50:04 +00:00
Ben McIlwain
33d30ea6a1 Improve PR polisher (#3067)
Enhances the `pr-polisher` skill to enforce stricter PR pre-flight checks:
- Added checks for extraneous files (package-lock.json).
- Added checks for missing license headers on new files across multiple languages.
- Added regex checks for codebase anti-patterns (FQNs, package visibility, UTC ZoneId, un-injected clocks, redundant transactions, etc.).
- Added regex checks for test anti-patterns (generic Exception catching, Truth Optional assertions, Thread.sleep).
- Enforced commit message body presence.
- Added a workflow step to explicitly verify commit message accuracy against the diff.
- Updated GEMINI.md to mandate the usage of the pr-polisher skill.
2026-05-28 19:32:33 +00:00
Ben McIlwain
00ee62f877 Update Netty and OkHttp dependencies and resolve test failures (#3066)
This commit updates several dependencies in dependencies.gradle and resolves the resulting test failures:
- Netty: Updated strict upper bound from <4.2.0 to <5.0.0 (resolved to 4.2.14.Final).
- OkHttp: Removed strict upper bound of <5.0.0 and moved to dynamic versions section (resolved to 5.3.2).
- Cleaned up dependencies.gradle by moving strict dependencies (secretmanager, common-protos, gax) out of the dynamic versions section.
- Updated all gradle.lockfile files.

Resulting test fixes:
- Netty: Replaced NioEventLoopGroup with DefaultEventLoopGroup in NettyExtension and ProbingStepTest. In Netty 4.2+, LocalServerChannel no longer supports registration with NIO-backed event loops, throwing an IllegalArgumentException.
- OkHttp: Refactored ServiceMonitoringClient to safely handle empty responses using Optional.orElse(). In OkHttp 5.x, a 204 No Content response returns a non-null ResponseBody with an empty string, causing an assertion failure where MosApiException was incorrectly bypassed.
2026-05-28 15:39:16 +00:00
Ben McIlwain
2bc07349a4 Address technical debt and improve safety in domain flows and models (#3065)
* Address technical debt and improve safety in domain flows and models

- Addressed unhandled empty lists and swallowed exceptions in DomainFlowTmchUtils.
- Improved null safety and immutability guarantees in Fee and LaunchPhase.
- Applied defensive copying in FeeTransformResponseExtension.
  Note: This uses the forceEmptyToNull(nullToEmptyImmutableCopy(...))
  pattern. This defensive copy ensures immutability, while forceEmptyToNull
  is required because JAXB will serialize an empty collection as an empty
  XML tag (which violates EPP XML schemas). Setting it to null ensures
  JAXB omits the tag entirely.
- Corrected JAXB property suppression in FeeCheckResponseExtensionItemStdV1.

* Add pr-polisher skill for automated PR pre-flight checks

* Enhance pr-polisher with more GEMINI.md constraints

Added checks for:
- Incorrect @Nullable imports.
- Unstatically imported utility methods (DateTimeUtils/CacheUtils).
- Redundant transaction wrapping (tm().transact -> tm().reTransact).
- Mutable collection instantiations (ArrayList/HashMap).
2026-05-27 21:45:11 +00:00
Juan Celhay
00522fb618 Change Kubernetes Services selectors to target "traffic" label (#3054)
* change spec.selector for kubernetes services

* now really change the selector
2026-05-27 18:59:37 +00:00
Ben McIlwain
ad992beff9 Add java-ast-refactoring skill (#3064)
This adds a Gemini CLI skill that leverages OpenRewrite to perform Abstract Syntax Tree (AST) based refactoring on Java codebases. It is highly preferred over text-based regex or python scripts because it understands Java semantics, correctly updates imports, and preserves formatting. A custom Python script is also included as a fallback for renaming fields and local variables.
2026-05-27 18:33:38 +00:00
Juan Celhay
ba91141505 Add postdeploy task in CD pipeline to tag deployed image (#3063)
* add variable for pipeline and region

* remove new lines from script

* add postdeploy task to tag images
2026-05-27 16:24:38 +00:00
gbrodman
c1ce73db49 Remove old unused GWT dependency (#3056) 2026-05-27 16:24:16 +00:00
Pavlo Tkach
00ceb6a7df Add Google Vacuum MGMT to schema allowed diff (#3062) 2026-05-27 15:48:31 +00:00
gbrodman
c731b18304 Replace unmaintained jsch dependency (#3061)
The old version https://mvnrepository.com/artifact/com.jcraft/jsch
hasn't been updated for like 8 years. This replaces it with the
community fork, https://github.com/mwiede/jsch.

It's theoretically possible to replace this with
https://github.com/apache/mina-sshd but it would require a lot more
changes and risk for not really any benefit.
2026-05-26 15:43:59 +00:00
Juan Celhay
5fd6e6cdaa Add a step to cloudbuild-nomulus CB job to create a release in Cloud Deploy (#3059)
* add step to create cd release in cb-nomulus job

* add variable for pipeline and region

* pass image with digest to release

* add source and skaffold to release command

* remove new lines from script
2026-05-26 14:32:38 +00:00
Ben McIlwain
53b92d602e Migrate EPP/Email from Soy to JAXB/FreeMarker (#3038)
- Replace deprecated Soy templates for EPP XML with JAXB models and a refined Fluent DSL.
- Migrate Spec11 and administrative emails to FreeMarker with HTML auto-escaping.
- Remove Soy compiler, Gradle tasks, and library dependencies.
- Address PR feedback regarding shadowing, version locking, and security warnings.
- Enhance tests with comprehensive XML equality assertions using Java 15 text blocks.
- Improve Javadocs and maintain strict temporal consistency using java.time.

FreeMarker replaces Soy for email templating, providing native HTML auto-escaping and allowing the removal of the complex 'soyToJava' compilation step from the build process. This significantly simplifies the build system and reduces maintenance overhead. For EPP XML, migrating to JAXB allows tool-generated commands to use the same model classes as the server-side EPP flows. This ensures that tool-generated XML is always schema-compliant and eliminates the risk of divergence between tool templates and actual server-side implementation. This unified approach provides compile-time type safety and improves developer ergonomics via a refined fluent DSL.

The base ImmutableObject class now provides a public clone() override that correctly resets the cached hashCode to null. This centralizes the custom cloning logic previously handled by a static helper and ensures that all subclasses—including the newly added JAXB models—satisfy CodeQL security requirements without needing redundant per-class overrides. The legacy static clone(T) helper has been updated to delegate to this instance method to maintain compatibility and architectural consistency.
2026-05-22 19:33:47 +00:00
gbrodman
b3fc57c7f7 Inject a singleton Gson instead of creating it many times (#3058)
Creation of Gson objects is nontrivial and it's thread-safe so we might
as well just use some singleton objects as much as possible rather than
recreating them.
2026-05-22 15:20:23 +00:00
Juan Celhay
bd70cd91a5 Add canary strategy to crash stage in Cloud Deploy pipeline (#3057)
* Add customCanaryDeployment strategy to crash

* change key to partialDeploymentAlertPolicyChecks

* add more indentation to alert policies config
2026-05-21 19:39:46 +00:00
gbrodman
73725e94fe Avoid injection of a possibly-null string value if thee Valkey cert key doesn't exist (#3055) 2026-05-20 20:02:35 +00:00
Juan Celhay
c3f8ec8c85 Generate partial phases kubernetes manifests in CB release job (#3048)
* generate kubernetes partial/canary manifests in release job

* rename partial phase labels

* replace container name value to be stage dependent

* just keep the new partial deployment update in the manifest generation
2026-05-20 16:44:45 +00:00
Weimin Yu
3894ca6971 More debugging code for replyTo address (#3053)
The  replyTo header works in manual tests. Add code emulating
BillingEmailUtils behavior and see if that causes the problem.

Also experimenting not to set the From header in GmaiClient, since
whatever we set is overridden anyway.
2026-05-19 21:02:01 +00:00
Weimin Yu
5f06581572 Add a reminder to run update_dependency to PR authors (#3050)
After the public-access removal from GCS buckets, the Kokoro tests can
no longer use our private repo for resolve dependencies. And breakage is
discovered only during build.

This PR lets Github to create review comment, which triggers on PRs that
contain *.lockfile changes and asks the PR author to confirm that the
update_dependency script has been executed.
2026-05-18 19:27:22 +00:00
gbrodman
17b851de42 Remove remaining references to contacts in XML files and flows (#2979)
This requires moving phone numbers from the contact XSD file to the
eppcommon XSD file (they're still used by registrars).

The remaining changes are related to removing the XML infrastructure
that allows for contacts and any uses of contacts.

We shouldn't merge this until
https://github.com/google/nomulus/pull/2954 is deployed to production
and has had a little bit to bake and make sure that nothing is wrong.
2026-05-18 18:55:00 +00:00
Pavlo Tkach
d30cc202d2 Replace CSRF source from cookie to header in the console requests (#3047)
* Update XSRF cookie to be a header

* Replace CSRF cookie with header
2026-05-15 17:45:33 +00:00
Juan Celhay
0998d5485c add additional label to nomulus deployments (#3046) 2026-05-14 20:01:18 +00:00
Juan Celhay
1bff89085b Build Cloud Deploy artifacts via Cloud Build job (#3044)
* add README

* updating comments/files
2026-05-14 15:35:32 +00:00
Weimin Yu
d9d83205c7 Verify user can send email (#3045)
Change the CannedScriptExecutionAction to send a email
message as a user-specified G workspace user.

This change is part of b/510340944, to verify that a newly
added dedicated sender is properly set up for sending emails.

Once the new sender is tested, the changes in this PR can be
dropped.
2026-05-14 15:13:57 +00:00
Ben McIlwain
56fe588b56 Complete Joda-Time to java.time migration (#3039)
This completes the exhaustive refactoring of foundational temporal types from Joda-Time to the native java.time API across the entire codebase.

- Replaced org.joda.time.DateTime, Instant, LocalDate, and Duration with java.time equivalents.
- Audited and updated Clock implementations (FakeClock, SystemClock). Added nowMillis(), nowDate(), and nowDateTime() to eliminate repetitive conversions and maintain parallel naming.
- Replaced ZonedDateTime with OffsetDateTime globally per go/avoid-zdt. OffsetDateTime is a better fit as we use a hardcoded ZoneOffset.UTC throughout the system, making geographical time zone rules (like daylight saving time) irrelevant and preventing serialization ambiguities. Added a presubmit check.
- Completely removed all transitional bridge methods from DateTimeUtils and deleted obsolete converters (e.g., DateTimeConverter).
- Updated testing infrastructure, Apache Beam pipelines, custom JCommander parameters, and networking modules to solely rely on java.time primitives.
- Retained the lone necessary org.joda.time.Instant usage in SafeBrowsingTransforms required by the Apache Beam API.
- Cleared Gradle lockfiles and removed the joda-time dependency entirely from the build configuration.
2026-05-13 16:07:19 +00:00
gbrodman
b33c2f4874 Add rdeEppParams to RDE output (#3041)
We mostly had the xsd code for this already, we just never actually used
it and added it to the output. Note that I had to make some changes to
allow the expected format (where some of the elements are empty).
2026-05-13 14:38:07 +00:00
gbrodman
b8f14fef8d Update Hibernate deps to 7.3.4 (#3040)
The fix for https://hibernate.atlassian.net/browse/HHH-20276 was
included in 7.3.4 and will be included in version 8 in the future. 8.x
is still in alpha though so we don't want to use it yet.
2026-05-12 17:58:49 +00:00
gbrodman
8047d1e3e3 Use remote caches in RDAP queries (#3034)
Note that this primarily affects domain lookups. We choose to use the
remote cache for hosts based on repo ID (not host name), so the remote
caches are not particularly useful for host lookups. We chose this
because the number of domain queries is orders of magnitude higher than
the number of host queries.
2026-05-12 16:28:36 +00:00
gbrodman
5854ccf00d Add (remote) cache metrics (#3033)
This only applies to the CacheModule-provided caches because we don't
want to have to deal with all the various other caches. We'll want to
know the various ratios between types of cache hits/misses when
evaluating the usefulness of the remote caching.
2026-05-11 18:19:52 +00:00
627 changed files with 6432 additions and 10064 deletions

View File

@@ -0,0 +1,30 @@
---
name: java-ast-refactoring
description: "AST-aware Java refactoring using OpenRewrite. Use when asked to structurally refactor Java code, change class names, change method signatures/overloads, replace builder patterns, modify annotations, or perform cross-file structural replacements. Note: Renaming fields or local variables/parameters is not supported natively via simple YAML recipes in the standard openrewrite modules."
---
# AST-Aware Java Refactoring
This skill uses OpenRewrite to perform Abstract Syntax Tree (AST) based refactoring on Java codebases. This is highly preferred over text-based regex or python scripts because it understands Java semantics, correctly updates imports, and preserves formatting.
## Parameter and Field Renaming (Last Resort)
Because OpenRewrite's YAML recipes do not natively support simple variable or field renaming, a custom script is provided:
```bash
python3 .gemini/skills/java-ast-refactoring/scripts/safe_rename.py <filepath> <old_name> <new_name>
```
**CRITICAL:** Running this python script is a LAST RESORT. It is a regex-based token replacement that ignores strings and comments, but it lacks true AST understanding. ALWAYS prefer using OpenRewrite recipes (`rewrite.yml`) for structural changes like renaming classes, methods, or moving targets, as OpenRewrite correctly handles imports, types, and cross-file references safely.
## Usage
1. Create a `rewrite.yml` recipe file in the workspace root. Refer to `.gemini/skills/java-ast-refactoring/references/rewrite_recipes.md` for syntax.
2. Execute the script:
```bash
./.gemini/skills/java-ast-refactoring/scripts/run_rewrite.sh rewrite.yml
```
3. The script will safely apply the AST transformations and then automatically run `./gradlew spotlessApply` and `./gradlew javaIncrementalFormatApply` on the modified files to automatically fix any Checkstyle line-length and import ordering issues caused by longer/shorter identifiers. Verify the output using `git diff`.
4. **MANDATORY:** Always run `./gradlew build -x test` (or the equivalent compile task) after running OpenRewrite to ensure no compilation errors were introduced.
## Known Limitations & Troubleshooting
* **Static Imports Dropped on Class Rename:** When using `ChangeType` to rename a class, OpenRewrite may sometimes drop static imports for fields/constants belonging to the old class instead of updating them to the new class. If compilation fails due to "cannot find symbol" for a constant after a class rename, manually restore the static import (e.g., `import static com.new.ClassName.CONSTANT;`).
* **Continuous Improvement:** If any new issues or edge cases are found while running the refactoring (e.g., build failures, formatting issues, or missed transformations), you **MUST** proactively ask the user if you should permanently update this skill file (`SKILL.md`) and its accompanying scripts (`scripts/run_rewrite.sh`, `scripts/safe_rename.py`) to fix the issue for future use. Do not wait for the user to prompt you to fix the infrastructure.

View File

@@ -0,0 +1,82 @@
# OpenRewrite Recipe Reference
OpenRewrite uses declarative YAML recipes to perform structural refactorings.
## Recipe Structure
A recipe file must have a `type`, a `name` (which you will activate), and a `recipeList` containing specific core recipes to execute sequentially.
```yaml
type: specs.openrewrite.org/v1beta/recipe
name: com.example.MyRefactoring
recipeList:
- <CoreRecipe>:
<argument1>: <value>
```
## Core Recipes for Common Operations
### 1. Change Method Name
```yaml
- org.openrewrite.java.ChangeMethodName:
methodPattern: java.util.Collections emptyList()
newMethodName: emptyList
```
### 2. Change Method Target to Static
Moves a method call to a new static method target. Useful for replacing custom utility methods with standard ones.
```yaml
- org.openrewrite.java.ChangeMethodTargetToStatic:
methodPattern: google.registry.model.eppinput.EppInputs createDomain(java.lang.String, java.lang.String)
fullyQualifiedTargetTypeName: google.registry.model.domain.DomainCommand.Create
returnType: google.registry.model.domain.DomainCommand.Create.Builder
```
### 3. Change Type (Rename/Move Class)
Updates the class name and automatically updates all imports across the codebase.
*Note: OpenRewrite occasionally drops `import static` references to fields inside the renamed class. Be prepared to manually restore them if a compilation error occurs.*
```yaml
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: org.joda.time.Instant
newFullyQualifiedTypeName: java.time.Instant
```
### 4. Remove Unused Imports
```yaml
- org.openrewrite.java.RemoveUnusedImports
```
### 5. Change Annotation
```yaml
- org.openrewrite.java.ChangeAnnotation:
annotationPattern: @org.junit.Ignore
newAnnotation: @org.junit.jupiter.api.Disabled
```
### 6. Remove Annotation
```yaml
- org.openrewrite.java.RemoveAnnotation:
annotationPattern: @java.lang.SuppressWarnings("unchecked")
```
### 7. Change Method Arguments
Reorders or removes arguments based on a target signature. `newArgumentTemplate` uses 0-based indexing.
```yaml
- org.openrewrite.java.ChangeMethodAccessLevel:
methodPattern: com.google.common.collect.ImmutableList of(..)
newAccessLevel: protected
```
### 8. Add Import
```yaml
- org.openrewrite.java.AddImport:
type: java.util.List
```
## Method Patterns
OpenRewrite uses a specific pointcut expression language for `methodPattern`:
* `[return-type] [fully-qualified-class-name] [method-name]([parameter-types])`
* `*` matches any type.
* `..` matches any number of parameters.
* Example: `java.lang.String split(java.lang.String, int)`
* Example: `* java.util.List add(..)`

View File

@@ -0,0 +1,80 @@
#!/bin/bash
# Copyright 2026 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Wrapper script to dynamically execute OpenRewrite without modifying build.gradle
if [ -z "$1" ]; then
echo "Usage: $0 <path-to-rewrite.yml>"
exit 1
fi
RECIPE_FILE=$(realpath "$1")
if [ ! -f "$RECIPE_FILE" ]; then
echo "Error: Recipe file $RECIPE_FILE not found."
exit 1
fi
# Extract the name of the recipe from the YAML to activate it
RECIPE_NAME=$(grep -oP '(?<=name: ).*' "$RECIPE_FILE" | head -n 1)
if [ -z "$RECIPE_NAME" ]; then
echo "Error: Could not extract 'name:' from $RECIPE_FILE"
exit 1
fi
INIT_SCRIPT="rewrite-init.gradle"
cat << EOF > "$INIT_SCRIPT"
initscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath("org.openrewrite.rewrite:org.openrewrite.rewrite.gradle.plugin:7.33.0")
}
}
rootProject {
apply plugin: org.openrewrite.gradle.RewritePlugin
rewrite {
activeRecipe("$RECIPE_NAME")
}
dependencies {
rewrite("org.openrewrite.recipe:rewrite-testing-frameworks:2.14.0")
rewrite("org.openrewrite.recipe:rewrite-migrate-java:2.11.0")
rewrite("org.openrewrite.recipe:rewrite-spring:5.7.0")
}
}
allprojects {
apply plugin: org.openrewrite.gradle.RewritePlugin
}
EOF
# Copy the recipe file to the workspace root temporarily so OpenRewrite finds it
cp "$RECIPE_FILE" ./rewrite.yml
echo "Executing OpenRewrite recipe: $RECIPE_NAME"
./gradlew --init-script "$INIT_SCRIPT" rewriteRun --no-parallel --no-configuration-cache
echo "Running code formatters to fix Checkstyle line-length and import ordering..."
./gradlew spotlessApply javaIncrementalFormatApply
# Clean up temporary files
rm "$INIT_SCRIPT"
rm ./rewrite.yml

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
# Copyright 2026 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import re
import os
def usage():
print("Usage: python safe_rename.py <filepath> <old_name> <new_name>")
print("Safely renames an identifier in a Java file, ignoring strings and comments.")
sys.exit(1)
def main():
if len(sys.argv) < 4:
usage()
filepath = sys.argv[1]
old_name = sys.argv[2]
new_name = sys.argv[3]
if not os.path.exists(filepath):
print(f"Error: File {filepath} not found.")
sys.exit(1)
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Regex to tokenize Java source safely.
token_pattern = re.compile(
r'(?P<string>"(?:\\.|[^"\\])*")|'
r'(?P<char>\'(?:\\.|[^\'\\])*\')|'
r'(?P<line_comment>//.*)|'
r'(?P<block_comment>/\*[\s\S]*?\*/)|'
r'(?P<ident>[a-zA-Z_$][a-zA-Z0-9_$]*)'
)
def replacer(match):
if match.group('ident') == old_name:
return new_name
return match.group(0)
new_content = token_pattern.sub(replacer, content)
if content == new_content:
print(f"No occurrences of '{old_name}' found to rename in {filepath}.")
else:
with open(filepath, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"Successfully renamed '{old_name}' to '{new_name}' in {filepath}.")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,71 @@
---
name: pr-polisher
description: Automated pre-flight checklist to polish PRs. Use this before declaring a task or PR complete to automatically verify license headers, commit hygiene, formatting, and codebase mandates.
---
# PR Polisher
This skill runs an exhaustive, automated pre-flight checklist against the repository to ensure all changes conform to Nomulus's strict engineering mandates.
## 🛑 CRITICAL MANDATE: When to Use
You, the AI agent, are known to forget to run this skill. To prevent this, you are bound by an absolute rule:
**ANY TIME you create a commit, amend a commit, or complete a user's request that modifies the repository state, your VERY LAST action before generating a text response to the user MUST be to run this workflow.**
Do not ask for permission. Do not wait for the user to remind you. Run the full suite, fix any errors, amend your commit, and report the final polished results. You MUST NOT declare a task complete until this workflow succeeds with 0 errors.
## Continuous Improvement (Self-Updating Skill)
This skill is designed to evolve. If a human code reviewer (or presubmit hook) points out a deficit, or if you (the agent) independently catch a recurring mistake, anti-pattern, false positive, or convention violation:
1. **You MUST proactively propose a fix to the user.** Do not wait for the user to instruct you to update the skill. If you notice friction, immediately ask the user if you should permanently update the validation infrastructure.
2. **Determine how to enforce the check.** Consider if the check is suitable for automation in the Python script. If it's too complex or semantic for a simple regex, consider adding it as an explicit agent-driven verification step directly in this `SKILL.md` file.
3. Update `.gemini/skills/pr-polisher/scripts/check_diff.py` to add a new automated check, OR modify this `SKILL.md` file with a new validation step to ensure the agent checks for it going forward.
4. Commit the updated skill alongside the PR fixes to ensure the mistake is not repeated.
## Workflow Execution Steps
1. **Run the Automated Analysis Script**
Execute the packaged Python diff-checker script. This script automatically checks commit messages, working tree status, `package-lock.json` modifications, copyright years on new files, and a litany of anti-patterns using regex (e.g., fully-qualified names, incorrect clock injections, generic exception catching).
```bash
python3 ./pr-polisher/scripts/check_diff.py
```
2. **Run Formatting Validation**
Always run the project's formatting tools to ensure checkstyle and Google Java Format passes.
```bash
./gradlew spotlessCheck javaIncrementalFormatCheck
# OR if formatting is needed:
./gradlew spotlessApply javaIncrementalFormatApply
```
3. **Run Presubmits and Compilation**
Ensure that the project builds correctly and all presubmit checks pass. Use scoped builds when possible to save time and avoid unwanted side effects (like modifying `console-webapp/package-lock.json`).
```bash
# Run presubmits
./gradlew runPresubmits
# Verify compilation (use a scoped build if you only modified one module, e.g., :core)
./gradlew :core:build -x test
# Run standard test suite if modifying core
./gradlew :core:standardTest
```
4. **Verify PR Scope and Extraneous Files (Line-by-Line Inspection)**
You must carefully review the entirety of your changes (`git diff HEAD^` or `git diff --cached`). Examine every single file and line changed to explicitly verify that the change *belongs* in this PR. You MUST look for and revert:
* **Irrelevant changes:** Formatting or refactoring in files unrelated to the PR's core purpose.
* **Accidental files:** Test output files, temp scripts, plan files (e.g., `codebase_review_plan.md`), scratchpads, or anything else generated during your workflow that shouldn't be committed.
* **Unintended side effects:** Changes to configuration files like `package-lock.json` unless explicitly required.
5. **Verify Test Coverage Additions (Line-by-Line Inspection)**
While looking at all the diffs, thoroughly check every single line to determine if any test changes or additions are necessary. If you have modified existing logic, added new branches, added a null check, or added new public methods, you MUST manually verify that the corresponding `Test.java` file covers these changes. If the test file or specific test cases do not exist, you must create them. A code review is not thorough if it only checks for compilation.
6. **Verify Commit Description Accuracy**
Re-read your commit message (`git log -1 --pretty=format:%B`). Compare it directly against the actual diff (`git diff HEAD^`) to verify that it completely and accurately describes ONLY the changes present in the commit.
* If the scope of the PR changed during prompting, you MUST update the commit message to reflect the final state of the code.
* Ensure that the primary purpose of the PR is mentioned first, and that no irrelevant or outdated changes from previous attempts are listed.
7. **Address Errors, Amend, and Re-Run (Iterative Checking)**
If any script throws an error, if scope was reduced, if the commit message was inaccurate, or if formatting changes were applied, you must stage those fixes and amend your commit:
```bash
git add -u
git commit --amend # Or git commit --amend --no-edit if only files changed
```
**CRITICAL:** You must loop back to Step 1 and run `python3 ./pr-polisher/scripts/check_diff.py` again. Continue this loop of checking and amending until the script definitively returns `0 ERRORS`, the build/presubmits pass, and the working directory is perfectly clean. Do not assume your fixes worked without re-running the check.

View File

@@ -0,0 +1,330 @@
#!/usr/bin/env python3
# Copyright 2026 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import subprocess
import re
import sys
import datetime
# Color codes
RED = "\03.3[91m"
YELLOW = "\03.3[93m"
GREEN = "\03.3[92m"
RESET = "\03.3[0m"
errors_found = 0
warnings_found = 0
def log_error(msg):
global errors_found
errors_found += 1
print(f"{RED}[ERROR]{RESET} {msg}")
def log_warning(msg):
global warnings_found
warnings_found += 1
print(f"{YELLOW}[WARNING]{RESET} {msg}")
def log_success(msg):
print(f"{GREEN}[OK]{RESET} {msg}")
def run_cmd(cmd):
return subprocess.check_output(cmd, shell=True, text=True).strip()
def check_single_commit():
print("--- Checking Commit Count ---")
try:
count = int(run_cmd("git rev-list --count HEAD ^master"))
if count > 1:
log_error(f"Branch contains {count} commits ahead of master. All changes for a single PR must be squashed into a single commit.")
else:
log_success("Branch contains a single commit.")
except Exception:
# Ignore errors if the git command fails (e.g. not a git repo or no master branch)
pass
def check_commit_message():
print("--- Checking Commit Message ---")
try:
msg = run_cmd("git log -1 --pretty=format:%B")
lines = msg.split('\n')
subject = lines[0]
if len(subject) > 50:
log_error(f"Commit subject exceeds 50 characters ({len(subject)} chars): '{subject}'")
if not subject[0].isupper():
log_error(f"Commit subject must be capitalized: '{subject}'")
if subject[-1] in ['.', '!', '?']:
log_error(f"Commit subject must not end with punctuation: '{subject}'")
has_body = False
for line in lines[1:]:
if line.strip() != "":
has_body = True
break
if not has_body:
log_error("Commit message must contain a comprehensive body detailing the 'what' and 'why'.")
if errors_found == 0:
log_success("Commit message format looks good.")
except Exception as e:
log_error(f"Failed to check commit message: {e}")
def check_workspace_clean():
print("\n--- Checking Workspace State ---")
status = run_cmd("git status --porcelain")
if status:
log_error("Workspace is not clean. Uncommitted changes found:\n" + status)
else:
log_success("Working directory is clean.")
def check_package_lock():
print("\n--- Checking package-lock.json ---")
diff_files = run_cmd("git diff HEAD^ --name-only").split('\n')
if "console-webapp/package-lock.json" in diff_files:
if "console-webapp/package.json" in diff_files or "dependencies.gradle" in diff_files:
log_warning("console-webapp/package-lock.json is modified in the diff. This is expected since dependencies were updated.")
else:
log_error("console-webapp/package-lock.json is modified in the diff. Unless NPM dependencies were explicitly changed, revert this file using: git checkout console-webapp/package-lock.json")
else:
log_success("console-webapp/package-lock.json is untouched.")
def check_license_headers():
print("\n--- Checking License Headers on New Files ---")
current_year = str(datetime.datetime.now().year)
added_files = run_cmd("git diff HEAD^ --name-status --diff-filter=A").split('\n')
java_header = f"// Copyright {current_year} The Nomulus Authors. All Rights Reserved."
script_header = f"# Copyright {current_year} The Nomulus Authors. All Rights Reserved."
sql_header = f"-- Copyright {current_year} The Nomulus Authors. All Rights Reserved."
ftl_header = f"<#-- Copyright {current_year} The Nomulus Authors. All Rights Reserved."
files_checked = 0
for f_line in added_files:
if not f_line:
continue
f = f_line.split('\t')[-1]
expected_header = None
if f.endswith('.java') or f.endswith('.js') or f.endswith('.gradle') or f.endswith('.ts'):
expected_header = java_header
elif f.endswith('.py') or f.endswith('.sh'):
expected_header = script_header
elif f.endswith('.sql'):
expected_header = sql_header
elif f.endswith('.ftl'):
expected_header = ftl_header
if expected_header:
files_checked += 1
try:
with open(f, 'r') as file:
content = file.read()
if expected_header not in content:
log_error(f"Missing or incorrect copyright year in {f}. Expected: {expected_header}")
except FileNotFoundError:
# File might have been deleted or renamed; ignore missing files.
pass
if files_checked == 0:
log_success("No new files requiring license headers added.")
def check_formatting():
print("\n--- Checking Project Formatting ---")
try:
run_cmd("./gradlew spotlessCheck javaIncrementalFormatCheck")
log_success("All formatting checks (spotless and javaIncrementalFormat) passed.")
except Exception as e:
log_error("Formatting checks failed. Run './gradlew spotlessApply javaIncrementalFormatApply' to fix.")
def check_diff_anti_patterns():
print("\n--- Checking Code Anti-Patterns in Diff ---")
diff = run_cmd("git diff HEAD^ -U0")
current_file = ""
# Regex Patterns
fqn_pattern = re.compile(r'(?<!import\s)(java|google\.registry|com\.google|org)\.[a-z0-9.]+\.[A-Z][a-zA-Z0-9]+')
visibility_pattern = re.compile(r'/\*\s*package\s*\*/')
utc_pattern = re.compile(r'ZoneId\.of\("UTC"\)')
now_pattern = re.compile(r'(Instant\.now\(\)|OffsetDateTime\.now\(\)|System\.currentTimeMillis\(\))')
catch_generic_pattern = re.compile(r'catch\s*\(\s*(Exception|Throwable)\s+[a-zA-Z0-9_]+\s*\)')
is_equal_optional_pattern = re.compile(r'\.isEqualTo\(Optional\.of\(')
sleep_pattern = re.compile(r'Thread\.sleep\(')
suppress_pattern = re.compile(r'@SuppressWarnings\(')
wrong_nullable_pattern = re.compile(r'import\s+(?!javax\.annotation\.Nullable;)[a-zA-Z0-9_.]+\.Nullable;')
utility_class_pattern = re.compile(r'\b(DateTimeUtils|CacheUtils)\.[a-z]')
redundant_tx_pattern = re.compile(r'tm\(\)\.transact\(\s*\(\)\s*->\s*tm\(\)\.reTransact')
mutable_collection_pattern = re.compile(r'new\s+(ArrayList|HashMap|HashSet)\s*[<()]')
trailing_space_pattern = re.compile(r'[ \t]+$')
debug_print_pattern = re.compile(r'(System\.(out|err)\.print|\.printStackTrace\(\))')
todo_pattern = re.compile(r'\b(TODO|FIXME)\b')
unnecessary_cast_pattern = re.compile(r'\(\s*(?:Instant|ImmutableSet|ImmutableList|ImmutableMap)(?:<[^>]+>)?\s*\)')
instant_tostring_pattern = re.compile(r'(?i)(?:instant|time|now|clock\.now\(\))\.toString\(\)')
dao_transact_pattern = re.compile(r'tm\(\)\.transact\(')
retransact_txtime_pattern = re.compile(r'tm\(\)\.reTransact\(\s*(?:\(\)\s*->\s*)?tm\(\)(?:\.|::)get(?:Transaction|Tx)Time\(\)?\s*\)')
inject_command_pattern = re.compile(r'inject\(Command\s+[a-zA-Z0-9_]+\)')
clock_now_pattern = re.compile(r'clock\.now\(\)')
suppress_count = 0
for line in diff.split('\n'):
if line.startswith('+++ b/'):
current_file = line[6:]
suppress_count = 0
continue
if line.startswith('+') and not line.startswith('+++'):
code_line = line[1:]
# Trailing whitespace
if trailing_space_pattern.search(code_line):
log_error(f"[{current_file}] Found trailing whitespace.")
# Skip regex definitions in this script from triggering false positives
if 're.compile' not in code_line:
# Debug prints
if debug_print_pattern.search(code_line):
log_error(f"[{current_file}] Found leftover debug print or stack trace (System. out. println / printStackTrace).")
# TODOs / FIXMEs
if todo_pattern.search(code_line):
log_warning(f"[{current_file}] Found new T" "ODO or F" "IXME. Ensure this is intentional before completing the PR.")
if not current_file.endswith('.java'):
continue
# FQN Check
fqn_matches = fqn_pattern.findall(code_line)
if fqn_matches:
# Skip if the match is exactly part of an import or package declaration
if not code_line.strip().startswith('import') and not code_line.strip().startswith('package'):
log_warning(f"[{current_file}] Potential Fully-Qualified Name found: {fqn_matches}. Use imports instead.")
# Package visibility
if visibility_pattern.search(code_line):
log_error(f"[{current_file}] Found '/* package */' modifier. Leave modifier blank instead.")
# Time zones
if utc_pattern.search(code_line):
log_error(f"[{current_file}] Found ZoneId.of(\"UTC\"). Use statically imported ZoneOffset.UTC instead.")
# System clocks
if now_pattern.search(code_line):
log_error(f"[{current_file}] Found un-injected clock (Instant.now / System.currentTimeMillis). Inject Clock instead.")
# Catch generic
if catch_generic_pattern.search(code_line):
log_warning(f"[{current_file}] Catching generic Exception/Throwable. Use specific exceptions.")
# Truth Optionals
if is_equal_optional_pattern.search(code_line):
log_warning(f"[{current_file}] Found .isEqualTo(Optional.of(...)). Use Truth's .hasValue(...) instead.")
# Thread.sleep
if sleep_pattern.search(code_line):
log_warning(f"[{current_file}] Found Thread.sleep(). Use Sleeper instead in tests.")
# SuppressWarnings
if suppress_pattern.search(code_line):
suppress_count += 1
if suppress_count > 1:
log_error(f"[{current_file}] Multiple @SuppressWarnings detected. They must be merged (e.g. {{\"unchecked\", \"foo\"}}).")
else:
suppress_count = 0
# Wrong Nullable
if wrong_nullable_pattern.search(code_line):
log_error(f"[{current_file}] Found incorrect Nullable import. Always use javax.annotation.Nullable.")
# Missing static imports for utilities
if utility_class_pattern.search(code_line):
if not code_line.strip().startswith('import'):
log_warning(f"[{current_file}] Found un-statically imported method from DateTimeUtils/CacheUtils. Use static imports.")
# Redundant transaction wrapping
if redundant_tx_pattern.search(code_line):
log_error(f"[{current_file}] Found redundant transaction wrapping (tm().transact(() -> tm().reTransact(...))).")
# Mutable collection instantiation
if mutable_collection_pattern.search(code_line):
log_warning(f"[{current_file}] Found mutable collection instantiation (ArrayList/HashMap/HashSet). Prefer Guava Immutable collections.")
# Unnecessary casts
if unnecessary_cast_pattern.search(code_line):
log_warning(f"[{current_file}] Potential unnecessary cast to Instant or Guava Immutable type. Remove if it compiles without it.")
# Instant toString
if instant_tostring_pattern.search(code_line):
log_error(f"[{current_file}] Found potential Instant.toString(). Use DateTimeUtils.formatInstant(...) to preserve .000Z precision.")
# DAO transactions
if current_file.lower().endswith('dao.java') and dao_transact_pattern.search(code_line):
log_error(f"[{current_file}] Found tm().transact(...) inside a DAO. Use tm().assertInTransaction() instead.")
# reTransact around getTxTime in production code
if 'src/main/' in current_file and retransact_txtime_pattern.search(code_line):
log_error(f"[{current_file}] Unnecessary reTransact() around getTxTime() in production code. Wrap the caller in a transaction instead.")
# inject(Command)
if inject_command_pattern.search(code_line):
log_error(f"[{current_file}] Generic inject(Command) methods do not work with Dagger. Use explicit concrete types.")
# clock.now() in tests
if 'src/test/' in current_file and clock_now_pattern.search(code_line):
log_warning(f"[{current_file}] Prefer using a fixed, static constant Instant over capturing clock.now() in tests to prevent flakiness.")
def check_missing_tests():
print("\n--- Checking for Missing Tests ---")
diff_files = run_cmd("git diff HEAD^ --name-only").split('\n')
main_files_modified = False
test_files_modified = False
for f in diff_files:
if f.startswith('core/src/main/') or f.startswith('util/src/main/'):
if f.endswith('.java'):
main_files_modified = True
if f.startswith('core/src/test/') or f.startswith('util/src/test/'):
if f.endswith('Test.java'):
test_files_modified = True
if main_files_modified and not test_files_modified:
log_warning("Production code (.java files in src/main/) was modified, but no corresponding tests (.java files in src/test/) were added or updated. You MUST proactively write tests for any new logic or bug fixes.")
else:
log_success("Test coverage check passed (tests were included or no production Java code was changed).")
def main():
print("========================================")
print(" NOMULUS PR POLISHER CHECKLIST ")
print("========================================\n")
check_single_commit()
check_commit_message()
check_workspace_clean()
check_package_lock()
check_license_headers()
check_missing_tests()
check_formatting()
check_diff_anti_patterns()
print("\n========================================")
if errors_found == 0 and warnings_found == 0:
print(f"{GREEN}SUCCESS: All checks passed. PR is polished!{RESET}")
else:
print(f"RESULTS: {RED}{errors_found} ERRORS{RESET}, {YELLOW}{warnings_found} WARNINGS{RESET}")
print("Please address the above issues before declaring the PR complete.")
sys.exit(1 if errors_found > 0 else 0)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,48 @@
name: Request Lockfile Review
on:
pull_request_target:
branches: ["master"]
types: [opened, synchronize, reopened]
jobs:
review-lockfiles:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
# We intentionally do NOT use actions/checkout here.
# This keeps the environment completely secure and satisfies CodeQL.
- name: Check files via GitHub API
id: check_files
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
// Get the list of files in the PR directly from the API
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
per_page: 100
});
// Look for any file **ending** in gradle.lockfile
const hasLockfile = files.some(file => file.filename.endsWith('gradle.lockfile'));
core.setOutput('has_lockfile', hasLockfile ? 'true' : 'false');
- name: Post unresolved review comment
if: steps.check_files.outputs.has_lockfile == 'true'
uses: actions/github-script@v7
with:
script: |
await github.rest.pulls.createReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
event: 'REQUEST_CHANGES',
body: `### ⚠️ Attention Required: Lockfile Detected\nThis pull request contains modifications to one or more \`*.lockfile\` files. Please confirm that you have run update_dependency.sh to push new dependencies to the private repo.\n\n_Someone with Admin role must manually dismiss this review before merging._`
});

8
.gitignore vendored
View File

@@ -1,5 +1,5 @@
/bazel-*
**/.idea/**
.jetskicli
######################################################################
# Java Ignores
@@ -115,11 +115,5 @@ cloudbuild-caches/
**/node_modules/**
/repos/
# Compiled JS/CSS code
core/**/registrar_bin*.js
core/**/registrar_dbg*.js
core/**/registrar_bin*.css
core/**/registrar_dbg*.css
# jEnv
.java-version

View File

@@ -13,21 +13,14 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Verification**: Before finalizing any change, scan the imports section for redundancy.
- **License Headers**: When creating new files, ensure the license header uses the current year (e.g., 2026). Existing files should retain their original year.
## 2. Time and Precision Handling (java.time Migration)
## 2. Time and Precision Handling
- **Idiomatic java.time Usage:** Avoid redundant conversions between `Instant` and `DateTime`. If a field or parameter is an `Instant`, use it directly. Do not convert to `DateTime` just to call a deprecated method if an `Instant` alternative exists or can be easily created. Furthermore, you should not call `toInstant()` or `toDateTime()` conversion methods when not strictly necessary; always prefer to use an alternative method that returns the correct type if one exists (e.g. use `tm().getTxTime()` which returns an `Instant` instead of calling `tm().getTransactionTime().toInstant()`).
- **CRITICAL MISTAKES TO AVOID:**
- NEVER use `toInstant(clock.nowUtc())` or `toInstant(fakeClock.nowUtc())`. Both `Clock` and `FakeClock` have a `now()` method that natively returns a `java.time.Instant`. You MUST use `clock.now()` or `fakeClock.now()` directly.
- NEVER double-wrap conversions like `toInstant(toDateTime(...))` or `toDateTime(toInstant(...))`.
- NEVER mark method parameters or local variables as `final` unnecessarily, as it clutters the codebase. For class fields and constants, use `final` where applicable (i.e. when the field is assigned once and never mutated) to enforce and communicate immutability.
- When using test helpers like `assertThatCommand().atTime(...)` or `ForeignKeyUtils.loadResource(...)`, ALWAYS use the `Instant` overloads. DO NOT wrap `Instant` instances in `toDateTime(...)` just to pass them to deprecated overloads.
- **UTC Timezones:** Do not use `ZoneId.of("UTC")`. Use a statically imported `UTC` from `ZoneOffset` instead (`import static java.time.ZoneOffset.UTC;`).
- **Millisecond Precision:** Always truncate `Instant.now()` to milliseconds (using `.truncatedTo(ChronoUnit.MILLIS)`) to maintain consistency with Joda `DateTime` and the PostgreSQL schema (which enforces millisecond precision via JPA converters).
- **Clock Injection:**
- Avoid direct calls to `Instant.now()`, `DateTime.now()`, `ZonedDateTime.now()`, or `System.currentTimeMillis()`.
- Avoid direct calls to `Instant.now()`, `OffsetDateTime.now()`, or `System.currentTimeMillis()`.
- Inject `google.registry.util.Clock` (production) or `google.registry.testing.FakeClock` (tests).
- Use `clock.nowDate()` to get a `ZonedDateTime` in UTC.
- When defining timestamps for tests, prefer using a fixed, static constant (e.g., `Instant.parse("2024-03-27T10:15:30.105Z")`) over capturing `clock.now()` to prevent flaky tests caused by the passage of real time. Avoid using the Unix epoch (`START_INSTANT`) unless specifically testing epoch-related logic; instead, use realistic dates and vary them across different test suites to ensure logic isn't dependent on a specific "standard" date.
- Use `clock.nowDate()` to get a `LocalDate` in UTC, or `clock.nowDateTime()` to get an `OffsetDateTime` in UTC.
- When defining timestamps for tests, prefer using a fixed, static constant (e.g., `Instant.parse("2024-03-27T10:15:30.105Z")`) over capturing `clock.now()` to prevent flaky tests caused by the passage of real time.
- **Beam Pipelines:**
- Ensure `Clock` is serializable (it is by default in this project) when used in Beam `DoFn`s.
- Pass the `Clock` through the constructor or via Dagger provider methods in the pipeline module.
@@ -42,7 +35,6 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Test Components:** Use `TestRegistryToolComponent` for command-line tool tests to bridge the gap between `main` and `nonprod/test` source sets.
### 4. Database Consistency
- **JPA Converters:** Be aware that JPA converters (like `DateTimeConverter`) may perform truncation or transformation. Ensure application-level logic matches these transformations to avoid "dirty" state or unexpected diffs.
- **Transaction Management:**
- **Top-Level:** Define database transactions (`tm().transact(...)`) at the highest possible level in the call chain (e.g., in an Action, a Command, or a Flow). This ensures all operations are atomic and handled by the retry logic.
- **DAO Methods:** Avoid declaring transactions inside low-level DAO methods. Use `tm().assertInTransaction()` to ensure that these methods are only called within a valid transactional context.
@@ -54,12 +46,21 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Transactional Time:** Ensure code that relies on `tm().getTransactionTime()` (or `tm().getTxTime()`) is executed within a transaction context.
### 5. Testing Best Practices
- **Mandatory Proactive Testing:** You MUST automatically write and update tests alongside your code changes WITHOUT waiting for the user to prompt you. If you add a new feature, fix a bug, or change core logic, you are explicitly required to identify the corresponding `*Test.java` file and implement comprehensive test coverage for your changes.
- **FakeClock and Sleeper:** Use `FakeClock` and `Sleeper` for any logic involving timeouts, delays, or expiration.
- **Empirical Reproduction:** Before fixing a bug, always create a test case that reproduces the failure.
- **Base Classes:** Leverage `CommandTestCase`, `EppToolCommandTestCase`, etc., to reduce boilerplate and ensure consistent setup (e.g., clock initialization).
- **Gradle Test Patterns:** When running tests to investigate fixes in the "core" directory, try to first use the "standardTest" Gradle task. It is faster than the "test" task, which includes the "fragileTest" task. Only run the full "test" task after "standardTest" succeeds.
### 6. Project Dependencies
- **Common Module:** When using `Clock` or other core utilities in a new or separate module (like `load-testing`), ensure `implementation project(':common')` is added to the module's `build.gradle`.
- **Updating Dependencies:** When updating third-party dependencies, you MUST follow this exact, non-negotiable sequence. NEVER run the update script without first verifying the lockfiles locally.
1. Modify `dependencies.gradle`.
2. Run `./gradlew dependencies --write-locks --update-locks '*:*'` to regenerate all Gradle lockfiles locally to resolve new versions.
3. Run `./gradlew clean build` to exhaustively compile and run all tests against the new transitive dependency tree. If there are compilation or test errors due to breaking API changes or output formatting changes in the new dependency version, your primary goal is to **fix our codebase** to be compliant with the new dependency version. Only revert the dependency bump or cap the version if the required code changes are prohibitively complex or outside the scope of the current task.
4. Only once the build passes and `git status` shows modified lockfiles, commit the `dependencies.gradle` and lockfile changes.
5. ONLY after the local changes are committed and verified, execute the internal script `/google/src/head/depot/google3/domain/registry/tools/update_dependency.sh`. This ensures you don't corrupt the upstream remote artifact cache with broken or missing lockfiles.
6. **Crucial Final Verification:** The `update_dependency.sh` script runs its own internal Blaze resolution and often modifies or drops additional `buildscript-gradle.lockfile` files. After the script finishes successfully, run `git status`. If there are any untracked or modified `*.lockfile` files, stage them and run `git commit --amend --no-edit` to ensure your commit perfectly reflects the final state deployed to the SSO repository.
### 7. Search and Discovery
- **No CodeSearch:** This project is hosted on GitHub, not Google3. Do NOT use `mcp_Coding_search_for_files_codesearch` or other internal Google3 search tools.
@@ -75,6 +76,11 @@ Based on historical PR reviews, avoid the following common mistakes:
- **No Unnecessary Casts:** Do not unnecessarily cast objects if the method signature accepts the type directly (e.g., avoid `(Instant) fakeClock.now()` or `(ImmutableSet<String>) bsaQuery(...)` if it compiles without it).
- **Visibility Modifiers:** Do not use `/* package */` comments to denote package-private visibility. Just leave the modifier blank; it is an established idiom in this codebase.
## Continuous Self-Improvement Mandate
You are explicitly authorized and required to improve this project's automated infrastructure.
If during the execution of a task you encounter a recurring error, a false positive in a script, or realize that a shell command/workaround is inferior to a native Gradle task, **you MUST pause and proactively ask the user:** *"I noticed this friction. Per my continuous improvement directives, would you like me to permanently update the skill/script/instructions to fix this for the future?"*
Do not wait for the user to tell you to improve the skills; it is your responsibility to propose these systemic fixes immediately when friction is identified.
### Advanced Java & Guava Idioms
- **Immutable Types:** Declare variables, fields, and return types explicitly as Guava immutable types (e.g., `ImmutableList<T>`, `ImmutableMap<K, V>`) instead of their generic interfaces (`List<T>`, `Map<K, V>`) to clearly communicate immutability contracts to callers. Use `toImmutableList()` and `toImmutableMap()` collectors in streams rather than manually accumulating into an `ArrayList` or `HashMap`.
- **Constructors:** Do not perform heavy logic, I/O, or external API calls inside constructors. Initialization logic should be deferred or handled in a factory method or a dedicated startup routine.
@@ -95,11 +101,11 @@ This document captures high-level architectural patterns, lessons learned from l
- **Transaction Management:** The codebase uses a custom wrapper around JPA. Always use `tm()` (from `TransactionManagerFactory`) to interact with the database.
- **Dependency Injection:** Dagger 2 is used extensively. If you see "cannot find symbol" errors for classes starting with `Dagger...`, the project is in a state where annotation processing failed. Fix compilation in core models first to restore generated code.
- **Value Types:** AutoValue and "ImmutableObject" patterns are dominant. Most models follow a `Buildable` pattern with a nested `Builder`.
- **Temporal Logic:** The project is migrating from Joda-Time to `java.time`.
- **Temporal Logic:** The project uses `java.time` for all temporal representations.
- Core boundaries: `DateTimeUtils.START_INSTANT` (Unix Epoch) and `DateTimeUtils.END_INSTANT` (Long.MAX_VALUE / 1000).
- Year Arithmetic: Use `DateTimeUtils.plusYears()` and `DateTimeUtils.minusYears()` to handle February 29th logic correctly.
## Source Control
- **No Unprompted Pushing:** You MUST NEVER push your changes to a remote repository (e.g., `git push origin ...`) unless the user VERY EXPLICITLY instructs you to do so. If you have finished a task, simply state that it is committed locally and ready for review. Do not assume pushing is desired.
- **Committing:** Always create a new commit on the branch if one hasn't been created yet for the branch's specific work. Only perform amending (`git commit --amend --no-edit`) for subsequent changes once the initial commit has been successfully created.
- **One Commit Per PR:** All changes for a single PR must be squashed into a single commit before merging.
- **Default to Amend:** Once an initial commit is created for a PR, all subsequent functional changes should be amended into that same commit by default (`git commit --amend --no-edit`). This ensures the PR remains a single, clean unit of work throughout the development lifecycle.
@@ -112,49 +118,37 @@ This document captures high-level architectural patterns, lessons learned from l
5. **Only after** step 4 has successfully returned a clean working directory may you generate a text response to the user declaring that the task is complete.
- **Diff Review:** Before finalizing a task, review the full diff (e.g., `git diff HEAD^`) to ensure all changes are functional and relevant. Identify and revert any formatting-only changes in files that do not contain functional updates to keep the commit focused.
## Self-Review Guidelines
Before finalizing any PR or declaring a task complete, you MUST perform a thorough, rigorous self-review of your entire diff. Run `git diff HEAD^` (or review the staged changes) and actively verify the following against every modified line:
## 🛑 CRITICAL: MANDATORY PR POLISHER EXECUTION
You, the AI agent, have a known failure mode of forgetting to run the PR polisher after making changes because you focus too narrowly on the immediate task. To prevent this, you are bound by the following absolute rule:
1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.time.Duration` and `org.joda.time.Duration`), one MUST remain fully qualified to avoid a compilation conflict.
2. **Redundant Conversions:** Did I use `toDateTime(clock.now())` where `clock.nowUtc()` would suffice? Did I use `toDateTime(END_INSTANT)` instead of `END_OF_TIME`? Did I use `.toInstant()` or `.toDateTime()` on something that could be avoided by using a different method overload (e.g., `tm().getTxTime()`)?
3. **Verbose Math:** Did I write any verbose time conversions inline? Are there `DateTimeUtils` methods I should be using instead? If not, should I abstract this math into `DateTimeUtils`?
4. **Assertion Cleanliness:** Am I polluting test assertions with `toDateTime(...)` wraps? If so, I need to add overloaded assertions to the Truth Subjects instead.
5. **Diff Scope:** Are there any formatting-only changes in files that I did not functionally modify? If so, revert them. Does the total line count of the diff align with the approved scope (e.g., ~1,000 lines for migrations)?
6. **Commit Message:** Does the commit message title fit within 50 characters? Does the body encapsulate the entirety of the changes across the diff cleanly and professionally?
7. **Missing Tests & Coverage:** *Perform a structured check for any new methods or modified behavior.* Did I add a new utility method (like `plusMonths(Instant, int)`) or change core logic? If so, I MUST open the corresponding test file and write tests to cover the new functionality (including edge cases, negative values, and leap years) before considering the task complete. A code review is not thorough if it only checks for compilation. I must actively ensure every new branch of logic has a test.
8. **Package Lock:** Did I include `console-webapp/package-lock.json` in my diff? If so, I MUST revert it (`git checkout console-webapp/package-lock.json`) unless I explicitly intended to modify NPM dependencies. This file is often modified by the build process and should not be committed accidentally.
**ANY TIME you create a commit, amend a commit, or complete a user's request that modifies the repository state, your VERY LAST action before generating a text response to the user MUST be to execute the `pr-polisher` skill.**
Do not ask for permission. Do not wait for the user to remind you. Run the full suite (`python3 .gemini/skills/pr-polisher/scripts/check_diff.py`, `runPresubmits`, `build`, and `test`), fix any errors, amend your commit, and report the final polished results in your response.
Only after actively confirming these checks against your diff are you permitted to finalize the task.
You MUST NOT declare a task done until this automated script returns 0 errors, the presubmits and tests pass, and the workspace is fully clean.
1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.util.Date` and `java.sql.Date`), one MUST remain fully qualified to avoid a compilation conflict.
2. **Diff Scope:** Are there any formatting-only changes in files that I did not functionally modify? If so, revert them. Does the total line count of the diff align with the approved scope (e.g., ~1,000 lines for migrations)?
3. **Commit Message:** Does the commit message title fit within 50 characters? Does the body encapsulate the entirety of the changes across the diff cleanly and professionally?
4. **Missing Tests & Coverage:** *Perform a structured check for any new methods or modified behavior.* Did I add a new utility method (like `plusMonths(Instant, int)`) or change core logic? If so, I MUST open the corresponding test file and write tests to cover the new functionality (including edge cases, negative values, and leap years) before considering the task complete. A code review is not thorough if it only checks for compilation. I must actively ensure every new branch of logic has a test.
5. **Package Lock:** Did I include `console-webapp/package-lock.json` in my diff? If so, I MUST revert it (`git checkout console-webapp/package-lock.json`) unless I explicitly intended to modify NPM dependencies. This file is often modified by the build process and should not be committed accidentally.
Only after actively executing the `pr-polisher` skill and confirming these checks against your diff are you permitted to finalize the task.
## Refactoring & Migration Guardrails
### 1. Compiler Warnings are Errors (`-Werror`)
This project treats Error Prone warnings as errors.
- **`@InlineMeSuggester`**: When creating deprecated Joda-Time bridge methods (e.g., `getTimestamp() -> return toDateTime(getTimestampInstant())`), you **MUST** immediately add `@SuppressWarnings("InlineMeSuggester")`. If you don't, the build will fail.
- **Repeatable Annotations**: `@SuppressWarnings` is **NOT** repeatable in this environment. If a method or class already has a suppression (e.g., `@SuppressWarnings("unchecked")`), you must merge them:
-`@SuppressWarnings("unchecked") @SuppressWarnings("InlineMeSuggester")`
-`@SuppressWarnings({"unchecked", "InlineMeSuggester"})`
-`@SuppressWarnings("unchecked") @SuppressWarnings("MustBeClosedChecker")`
-`@SuppressWarnings({"unchecked", "MustBeClosedChecker"})`
### 2. Resolving Ambiguity
- **Null Overloads**: Adding an `Instant` overload to a method that previously took `DateTime` will break all `create(null)` calls. You must cast them: `create((Instant) null)`.
- **Type Erasure**: Methods taking `Optional<DateTime>` and `Optional<Instant>` will clash due to erasure. Use distinct names, e.g., `setAutorenewEndTimeInstant(Optional<Instant> time)`.
### 3. Build Strategy
- **Surgical Changes**: In large-scale migrations, focus on "leaf" nodes first (Utilities -> Models -> Flows -> Actions).
- **PR Size**: Minimize PR size by retaining Joda-Time bridge methods for high-level "Action" and "Flow" classes unless a full migration is requested. Reverting changes to DNS and Reporting logic while updating the underlying models is a valid strategy to keep PRs reviewable.
### 2. Build Strategy
- **Validation**: Always run `./gradlew build -x test` before attempting to run unit tests. Unit tests will not run if there are compilation errors in any part of the `core` module. Before finalizing a PR or declaring a task done, you MUST verify your changes. **Prefer scoped builds** (e.g., `./gradlew :core:build`) if you are only modifying backend Java code. Running the global `./gradlew build` triggers the frontend `console-webapp` build, which unnecessarily runs `npmInstallDeps` and modifies `package-lock.json`. If you must run a global build, you must revert `console-webapp/package-lock.json` afterwards. Do not declare success if formatting checks (e.g., `spotlessCheck` or `javaIncrementalFormatCheck`) or tests fail. If formatting fails, run `./gradlew spotlessApply` and then re-run your build command to verify everything passes.
## 🚫 Common Pitfalls to Avoid
- **Mixing Joda and Java Durations:** Methods like `Tld.get().getRenewGracePeriodLength()` return a **Joda** `Duration`, which cannot be passed directly to `Instant.plus(...)` because it doesn't implement `TemporalAmount`. You MUST use `.plusMillis(duration.getMillis())` instead.
- **Serialization Precision (`.000Z`):** When asserting against or generating XML/YAML files, remember that millisecond precision (`.000Z`) is required. Always use `DateTimeUtils.formatInstant(...)` to format `Instant` objects (it preserves the `.000Z` suffix) instead of `Instant.toString()` (which drops it for exact seconds). We have added custom Jackson `InstantKeySerializer`s for this purpose, but you must keep this precision in mind when manually updating `.xml` or `.yaml` test data.
- **Static Imports:** Methods like `toDateTime`, `toInstant`, `plusYears`, `plusMonths`, and `minusDays` from `DateTimeUtils` MUST be statically imported. Do NOT use them fully qualified (e.g., `DateTimeUtils.plusMonths(...)`).
- **Redundant Parses:** Never write `toDateTime(Instant.parse(...))` or `toInstant(DateTime.parse(...))`. If you need a `DateTime`, use `DateTime.parse(...)` directly. If you need an `Instant`, use `Instant.parse(...)` directly.
- **cloneProjectedAtTime vs cloneProjectedAtTime:** When converting tests and logic that use `clock.now()` to project resource state into the future or past, do not wrap the Java `Instant` in `toDateTime()` just to call `cloneProjectedAtTime()`. Instead, switch the method call to use the native `cloneProjectedAtTime()` method which is available on all `EppResource` models.
- **Do not go in circles with the build:** If you see an `InlineMeSuggester` error, apply the suppression to **ALL** similar methods in that file and related files in one turn. Do not fix them one by one. Furthermore, do not run a global `./gradlew build` when a scoped `./gradlew :core:build` or `./gradlew :core:test` is faster and more appropriate. Run global builds only when doing final verification.
- **Exception Conversion in Tests:** When migrating time types (e.g., from Joda `DateTime` to Java `Instant`), be extremely careful with tests that verify parsing failures (e.g., `assertThrows(IllegalArgumentException.class, ...)`). Joda's `DateTime.parse()` throws an `IllegalArgumentException` on failure, but `Instant.parse()` throws a `java.time.format.DateTimeParseException`. You must update the expected exception type in these tests to ensure they actually test the correct behavior, and verify the tests are not failing prematurely on the first line if it contains invalid data meant to be ignored.
- Dagger/AutoValue corruption: If you modify a builder or a component incorrectly, Dagger will fail to generate code, leading to hundreds of "cannot find symbol" errors. If this happens, `git checkout` the last working state of the specific file and re-apply changes more surgically.
- **`replace` tool context**: When using `replace` on large files (like `Tld.java` or `DomainBase.java`), provide significant surrounding context. These files have many similar method signatures (getters/setters) that can lead to incorrect replacements.

View File

@@ -609,3 +609,23 @@ gradle.taskGraph.whenReady { graph ->
}
}
}
task fastBuild {
group = 'build'
description = 'A lightweight build for local dev. Compiles Java, runs standard tests, and checks formatting, but skips Docker images, fragile tests, and the massive Angular console builds. (Do not use this target to verify console changes.)'
dependsOn build
// Remove the heavy default dependencies specifically for fastBuild
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(fastBuild)) {
project(':console-webapp').tasks.named('buildConsoleForAll').get().enabled = false
project(':jetty').tasks.named('buildNomulusImage').get().enabled = false
project(':core').tasks.named('buildToolImage').get().enabled = false
project(':core').tasks.named('fragileTest').get().enabled = false
project(':jetty').tasks.named('stage').get().enabled = false
if (project.tasks.findByName('stage') != null) {
project.tasks.named('stage').get().enabled = false
}
}
}
}

View File

@@ -58,7 +58,7 @@ dependencies {
implementation deps['com.google.code.findbugs:jsr305']
implementation deps['com.google.guava:guava']
implementation deps['jakarta.inject:jakarta.inject-api']
implementation deps['joda-time:joda-time']
implementation deps['org.freemarker:freemarker']
implementation deps['com.google.flogger:flogger']
implementation deps['io.github.java-diff-utils:java-diff-utils']
implementation deps['com.google.truth:truth']

View File

@@ -2,7 +2,7 @@
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.2.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.github.ben-manes.caffeine:caffeine:3.2.4=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
@@ -11,8 +11,8 @@ com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor,te
com.google.code.findbugs:jsr305:3.0.2=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.36.0=checkstyle
com.google.errorprone:error_prone_annotations:2.43.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.49.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.flogger:flogger:0.9=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
@@ -34,10 +34,9 @@ commons-collections:commons-collections:3.2.2=checkstyle
info.picocli:picocli:4.7.7=checkstyle
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.16=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
io.github.java-diff-utils:java-diff-utils:4.17=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
jakarta.inject:jakarta.inject-api:2.0.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
javax.inject:javax.inject:1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
joda-time:joda-time:2.14.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
net.sf.saxon:Saxon-HE:12.5=checkstyle
org.antlr:antlr4-runtime:4.13.2=checkstyle
@@ -61,6 +60,7 @@ org.codehaus.plexus:plexus-classworlds:2.6.0=checkstyle
org.codehaus.plexus:plexus-component-annotations:2.1.0=checkstyle
org.codehaus.plexus:plexus-container-default:2.1.0=checkstyle
org.codehaus.plexus:plexus-utils:3.3.0=checkstyle
org.freemarker:freemarker:2.3.34=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.jacoco:org.jacoco.agent:0.8.14=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.14=jacocoAnt
@@ -68,12 +68,12 @@ org.jacoco:org.jacoco.core:0.8.14=jacocoAnt
org.jacoco:org.jacoco.report:0.8.14=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.jspecify:jspecify:1.0.0=annotationProcessor,checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
org.junit.jupiter:junit-jupiter-api:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.13.4=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:6.1.0=testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.9=jacocoAnt
org.ow2.asm:asm-tree:9.9=jacocoAnt

View File

@@ -16,15 +16,16 @@ package google.registry.util;
import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import javax.annotation.concurrent.ThreadSafe;
/**
* A clock that tells the current time in milliseconds or nanoseconds.
*
* <p>Clocks are technically serializable because they are either a stateless wrapper around the
* system clock, or for testing, are just a wrapper around a DateTime. This means that if you
* system clock, or for testing, are just a wrapper around an Instant. This means that if you
* serialize a clock and deserialize it elsewhere, you won't necessarily get the same time or time
* zone -- what you will get is a functioning clock.
*/
@@ -34,8 +35,18 @@ public interface Clock extends Serializable {
/** Returns current Instant (which is always in UTC). */
Instant now();
/** Returns the current time as a {@link ZonedDateTime} in UTC. */
default ZonedDateTime nowDate() {
return ZonedDateTime.ofInstant(now(), ZoneOffset.UTC);
/** Returns the current time as an {@link OffsetDateTime} in UTC. */
default OffsetDateTime nowDateTime() {
return OffsetDateTime.ofInstant(now(), ZoneOffset.UTC);
}
/** Returns the current time as a {@link LocalDate} in UTC. */
default LocalDate nowDate() {
return LocalDate.ofInstant(now(), ZoneOffset.UTC);
}
/** Returns the current time in milliseconds since the epoch. */
default long nowMillis() {
return now().toEpochMilli();
}
}

View File

@@ -15,7 +15,6 @@
package google.registry.util;
import static com.google.common.base.Preconditions.checkArgument;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -24,14 +23,8 @@ import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.ReadableDuration;
public abstract class DateTimeUtils {
@@ -52,15 +45,15 @@ public abstract class DateTimeUtils {
*
* <p>Example: {@code 2024-03-27T10:15:30.105Z}
*
* <p>Handles large/negative years by using a sign prefix if necessary, compatible with {@link
* Instant#parse}.
* <p>Note: We deliberately strip the leading {@code +} sign from the formatted year field if
* present. While standard ISO 8601 specifies that years with more than 4 digits should be
* prefixed with a {@code +} sign, W3C XML Schema 1.0 (which our EPP RDE XSD uses) strictly
* forbids leading plus signs in {@code xsd:dateTime} strings. Suppressing the plus sign ensures
* our generated XML continues to pass strict XSD validation for large years (e.g. {@code
* 294247-01-10T04:00:54.775Z}).
*/
private static final DateTimeFormatter ISO_8601_FORMATTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NOT_NEGATIVE)
.appendPattern("-MM-dd'T'HH:mm:ss.SSS'Z'")
.toFormatter()
.withZone(ZoneOffset.UTC);
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC);
/** A formatter that produces lowercase, filename-safe and job-name-safe timestamps. */
public static final DateTimeFormatter LOWERCASE_TIMESTAMP_FORMATTER =
@@ -68,7 +61,8 @@ public abstract class DateTimeUtils {
/** Formats an {@link Instant} to an ISO-8601 string. */
public static String formatInstant(Instant instant) {
return ISO_8601_FORMATTER.format(instant);
String formatted = ISO_8601_FORMATTER.format(instant);
return formatted.startsWith("+") ? formatted.substring(1) : formatted;
}
/**
@@ -79,9 +73,15 @@ public abstract class DateTimeUtils {
* large years (e.g. {@code 294247-01-10T04:00:54.775Z}).
*/
public static Instant parseInstant(String timestamp) {
if (!timestamp.startsWith("+") && !timestamp.startsWith("-")) {
int dashIndex = timestamp.indexOf('-');
if (dashIndex > 4) {
timestamp = "+" + timestamp;
}
}
try {
// Try the standard millisecond precision format first.
return Instant.from(ISO_8601_FORMATTER.parse(timestamp));
return Instant.from(DateTimeFormatter.ISO_INSTANT.parse(timestamp));
} catch (DateTimeParseException e) {
// Fall back to the standard ISO instant parser which handles varied precision.
return Instant.parse(timestamp);
@@ -93,7 +93,7 @@ public abstract class DateTimeUtils {
return earliestOf(Lists.asList(first, rest));
}
/** Returns the earliest element in a {@link Instant} iterable. */
/** Returns the earliest element in an {@link Instant} iterable. */
public static Instant earliestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().min(instants);
@@ -104,24 +104,12 @@ public abstract class DateTimeUtils {
return latestOf(Lists.asList(first, rest));
}
/** Returns the latest element in a {@link Instant} iterable. */
/** Returns the latest element in an {@link Instant} iterable. */
public static Instant latestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().max(instants);
}
/** Converts a Joda-Time Duration to a java.time.Duration. */
@Nullable
public static java.time.Duration toJavaDuration(@Nullable ReadableDuration duration) {
return duration == null ? null : java.time.Duration.ofMillis(duration.getMillis());
}
/** Converts a java.time.Duration to a Joda-Time Duration. */
@Nullable
public static org.joda.time.Duration toJodaDuration(@Nullable java.time.Duration duration) {
return duration == null ? null : org.joda.time.Duration.millis(duration.toMillis());
}
/** Returns whether the first {@link Instant} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(Instant timeToCheck, Instant timeToCompareTo) {
return !timeToCheck.isAfter(timeToCompareTo);
@@ -134,7 +122,7 @@ public abstract class DateTimeUtils {
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link java.time.ZonedDateTime#plusYears} to ensure that we never end up on February 29.
* {@link java.time.OffsetDateTime#plusYears} to ensure that we never end up on February 29.
*/
public static Instant plusYears(Instant now, int years) {
checkArgument(years >= 0);
@@ -157,7 +145,7 @@ public abstract class DateTimeUtils {
/**
* Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead
* of {@link java.time.ZonedDateTime#minusYears} to ensure that we never end up on February 29.
* of {@link java.time.OffsetDateTime#minusYears} to ensure that we never end up on February 29.
*/
public static Instant minusYears(Instant now, long years) {
checkArgument(years >= 0);
@@ -171,24 +159,6 @@ public abstract class DateTimeUtils {
return instant.atZone(ZoneOffset.UTC).toLocalDate();
}
/** Convert a joda {@link DateTime} to a java.time {@link Instant}, null-safe. */
@Nullable
public static Instant toInstant(@Nullable DateTime dateTime) {
return (dateTime == null) ? null : Instant.ofEpochMilli(dateTime.getMillis());
}
/** Convert a java.time {@link Instant} to a joda {@link DateTime}, null-safe. */
@Nullable
public static DateTime toDateTime(@Nullable Instant instant) {
return (instant == null) ? null : new DateTime(instant.toEpochMilli(), UTC);
}
/** Convert a java.time {@link java.time.Instant} to a joda {@link org.joda.time.Instant}. */
@Nullable
public static org.joda.time.Instant toJodaInstant(@Nullable java.time.Instant instant) {
return (instant == null) ? null : org.joda.time.Instant.ofEpochMilli(instant.toEpochMilli());
}
public static Instant plusHours(Instant instant, long hours) {
return instant.plus(hours, ChronoUnit.HOURS);
}

View File

@@ -31,10 +31,9 @@ public class SystemClock implements Clock {
@Override
public Instant now() {
// Truncate to milliseconds to match the precision of Joda DateTime and our database schema
// (which uses millisecond precision via DateTimeConverter). This prevents subtle comparison
// bugs where a high-precision Instant would be considered "after" a truncated database
// timestamp.
// Truncate to milliseconds to match the precision of our database schema.
// This prevents subtle comparison bugs where a high-precision Instant would be
// considered "after" a truncated database timestamp.
return Instant.now().truncatedTo(MILLIS);
}
}

View File

@@ -0,0 +1,67 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.util;
import com.google.common.collect.ImmutableMap;
import freemarker.core.HTMLOutputFormat;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import jakarta.inject.Inject;
import java.io.StringWriter;
/**
* A utility class for rendering FreeMarker templates.
*
* <p>This renderer is configured to use HTML as the default output format, which enables automatic
* escaping of all interpolated variables. It also uses the "computer" number format to ensure
* consistent formatting of numeric values across different locales.
*/
public class TemplateRenderer {
private final Configuration configuration;
@Inject
public TemplateRenderer() {
this.configuration = new Configuration(Configuration.VERSION_2_3_32);
this.configuration.setClassLoaderForTemplateLoading(getClass().getClassLoader(), "");
this.configuration.setDefaultEncoding("UTF-8");
this.configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
this.configuration.setLogTemplateExceptions(false);
this.configuration.setWrapUncheckedExceptions(true);
this.configuration.setFallbackOnNullLoopVariable(false);
this.configuration.setOutputFormat(HTMLOutputFormat.INSTANCE);
this.configuration.setNumberFormat("computer");
}
/**
* Renders the specified template with the given data model.
*
* @param templatePath the path to the template file relative to the classpath root
* @param dataModel an immutable map containing the data to be used in the template
* @return the rendered template as a string
* @throws RuntimeException if the template cannot be found, parsed, or processed
*/
public String render(String templatePath, ImmutableMap<String, Object> dataModel) {
try {
Template template = configuration.getTemplate(templatePath);
StringWriter writer = new StringWriter();
template.process(dataModel, writer);
return writer.toString();
} catch (Exception e) {
throw new RuntimeException(String.format("Error rendering template %s", templatePath), e);
}
}
}

View File

@@ -0,0 +1,83 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.util;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableMap;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link TemplateRenderer}. */
class TemplateRendererTest {
private final TemplateRenderer renderer = new TemplateRenderer();
@Test
void testRender_success() {
ImmutableMap<String, Object> data =
ImmutableMap.of(
"name", "World", "score", 42, "showMessage", true, "message", "Keep going!");
String result = renderer.render("google/registry/util/test_template.ftl", data);
assertThat(result).isEqualTo("Hello World!\nYour score is 42.\nMessage: Keep going!\n");
}
@Test
void testRender_conditional_false() {
ImmutableMap<String, Object> data =
ImmutableMap.of("name", "User", "score", 0, "showMessage", false);
String result = renderer.render("google/registry/util/test_template.ftl", data);
assertThat(result).isEqualTo("Hello User!\nYour score is 0.\n");
}
@Test
void testRender_htmlEscaping() {
ImmutableMap<String, Object> data =
ImmutableMap.of("name", "<b>World</b>", "score", 42, "showMessage", false);
String result = renderer.render("google/registry/util/test_template.ftl", data);
assertThat(result).contains("Hello &lt;b&gt;World&lt;/b&gt;!");
}
@Test
void testRender_missingTemplate_throwsException() {
assertThrows(
RuntimeException.class,
() -> renderer.render("non/existent/template.ftl", ImmutableMap.of()));
}
@Test
void testRender_missingVariable_throwsException() {
// The template expects 'name', 'score', and 'showMessage', but the map is empty.
assertThrows(
RuntimeException.class,
() -> renderer.render("google/registry/util/test_template.ftl", ImmutableMap.of()));
}
@Test
void testRender_unusedVariable_ignored() {
ImmutableMap<String, Object> data =
ImmutableMap.of(
"name",
"User",
"score",
100,
"showMessage",
false,
"unusedKey",
"This should be ignored");
String result = renderer.render("google/registry/util/test_template.ftl", data);
assertThat(result).isEqualTo("Hello User!\nYour score is 100.\n");
}
}

View File

@@ -0,0 +1,6 @@
<#-- Copyright 2026 The Nomulus Authors. All Rights Reserved. -->
Hello ${name}!
Your score is ${score}.
<#if showMessage>
Message: ${message}
</#if>

View File

@@ -21,8 +21,6 @@ import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
import org.joda.time.ReadableInstant;
/** A mock clock for testing purposes that supports telling, setting, and advancing the time. */
@ThreadSafe
@@ -41,12 +39,6 @@ public final class FakeClock implements Clock {
this(START_INSTANT);
}
/** Creates a FakeClock initialized to a specific time. */
@Deprecated
public FakeClock(ReadableInstant startTime) {
setTo(startTime);
}
/** Creates a FakeClock initialized to a specific time. */
public FakeClock(Instant startTime) {
setTo(startTime);
@@ -66,12 +58,6 @@ public final class FakeClock implements Clock {
* @param autoIncrementStep the new auto increment duration
* @return this
*/
@Deprecated
public FakeClock setAutoIncrementStep(ReadableDuration autoIncrementStep) {
this.autoIncrementStepMs = autoIncrementStep.getMillis();
return this;
}
/**
* Sets the increment applied to the clock whenever it is queried. The increment is zero by
* default: the clock is left unchanged when queried.
@@ -91,23 +77,11 @@ public final class FakeClock implements Clock {
advanceBy(Duration.ofMillis(1));
}
/** Advances clock by some duration. */
@Deprecated
public void advanceBy(ReadableDuration duration) {
currentTimeMillis.addAndGet(duration.getMillis());
}
/** Advances clock by some duration. */
public void advanceBy(Duration duration) {
currentTimeMillis.addAndGet(duration.toMillis());
}
/** Sets the time to the specified instant. */
@Deprecated
public void setTo(ReadableInstant time) {
currentTimeMillis.set(time.getMillis());
}
/** Sets the time to the specified instant. */
public void setTo(Instant time) {
currentTimeMillis.set(time.toEpochMilli());

View File

@@ -409,4 +409,3 @@ if __name__ == '__main__':
sys.exit(main(sys.argv))
except Abort as ex:
sys.exit(1)

View File

@@ -90,18 +90,34 @@ PRESUBMITS = {
# License check
PresubmitCheck(
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts"), {
("java", "js", "sql", "py", "sh", "gradle", "ts", "ftl"), {
".git", "/build/", "node_modules/", "LoggerConfig.java", "registrar_bin.",
"registrar_dbg.", "google-java-format-diff.py",
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js"
"nomulus.golden.sql", "javascript/checks.js"
}, REQUIRED):
"File did not include the license header.",
# Files must end in a newline
PresubmitCheck(r".*\n$", ("java", "js", "soy", "sql", "py", "sh", "gradle", "ts", "xml"),
PresubmitCheck(r".*\n$", ("java", "js", "sql", "py", "sh", "gradle", "ts", "xml", "ftl"),
{"node_modules/", ".idea"}, REQUIRED):
"Source files must end in a newline.",
# Files must not end with extraneous blank lines
PresubmitCheck(
r".*\n\n$",
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts", "xml"),
{"node_modules/", ".idea", "nomulus.golden.sql"},
):
"Source files must not end with extraneous blank lines.",
# Duplicate empty lines
PresubmitCheck(
r".*\n\n\n.*",
("java", "js", "soy", "sh", "gradle", "ts", "xml"),
{"node_modules/", ".idea"},
):
"Source files must not contain duplicate empty lines.",
# System.(out|err).println should only appear in tools/ or load-testing/
PresubmitCheck(
r".*\bSystem\s*\.\s*(?:out|err)\s*\.\s*print.*", "java", {
@@ -111,33 +127,6 @@ PRESUBMITS = {
"System.(out|err).println is only allowed in tools/ packages. Please "
"use a logger instead.",
# Various Soy linting checks
PresubmitCheck(
r".* (/\*)?\* {?@param ",
"soy",
{},
):
"In SOY please use the ({@param name: string} /** User name. */) style"
" parameter passing instead of the ( * @param name User name.) style "
"parameter passing.",
PresubmitCheck(
r'.*\{[^}]+\w+:\s+"',
"soy",
{},
):
"Please don't use double-quoted string literals in Soy parameters",
PresubmitCheck(
r'.*autoescape\s*=\s*"[^s]',
"soy",
{},
):
"All soy templates must use strict autoescaping",
PresubmitCheck(
r".*noAutoescape",
"soy",
{},
):
"All soy templates must use strict autoescaping",
PresubmitCheck(
r".*\nimport\s+(?:static\s+)?.*\.shaded\..*",
"java",
@@ -160,7 +149,8 @@ PRESUBMITS = {
"SelfSignedCaCertificate.java",
"X509Utils.java",
"TmchCertificateAuthority.java",
"DelegatedCredentials.java"
"DelegatedCredentials.java",
"SslInitializerTestUtils.java"
},
):
"Do not use java.util.Date. Use classes in java.time package instead.",
@@ -202,85 +192,24 @@ PRESUBMITS = {
{},
):
"Do not use .isEqualTo(Optional.of(...)). Use Truth's .hasValue(...) instead.",
# TODO: Remove the java.time migration presubmit checks below once the entire codebase has been migrated to java.time.
PresubmitCheck(
r".*toDateTime\(\s*toInstant\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not double-wrap toDateTime(toInstant(...)).",
PresubmitCheck(
r".*toInstant\(\s*toDateTime\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not double-wrap toInstant(toDateTime(...)).",
PresubmitCheck(
r".*toInstant\([^;]*[cC]lock\.now\(\).*",
r".*java\.time\.ZonedDateTime.*",
"java",
{},
):
"Do not use toInstant(clock.now()). Use clock.now() instead.",
PresubmitCheck(
r".*toDateTime\([^;]*[cC]lock\.now\(\).*",
"java",
{},
):
"Do not use toDateTime(clock.now()). Use clock.now() and Instant overloads instead.",
PresubmitCheck(
r".*toInstant\([^;]*tm\(\)\.getTxTime\(\).*",
"java",
{},
):
"Do not use toInstant(tm().getTxTime()). Use tm().getTxTime() instead.",
PresubmitCheck(
r".*toDateTime\([^;]*tm\(\)\.getTxTime\(\).*",
"java",
{},
):
"Do not use toDateTime(tm().getTxTime()). Use tm().getTxTime() and Instant overloads instead.",
PresubmitCheck(
r".*\(\s*Instant\s*\)\s*(?:this\.)?(?:fakeClock|clock)\.now\(\s*\).*",
"java",
{},
):
"Do not unnecessarily cast clock.now() to Instant.",
PresubmitCheck(
r".*toDateTime\(\s*Instant\.now\(.*",
"java",
{},
):
"Do not wrap Instant.now() in toDateTime. Use DateTime.now(UTC) directly.",
PresubmitCheck(
r".*toInstant\(\s*DateTime\.now\(.*",
"java",
{},
):
"Do not wrap DateTime.now() in toInstant. Use Instant.now().truncatedTo(ChronoUnit.MILLIS) directly.",
PresubmitCheck(
r".*toDateTime\(\s*Instant\.parse\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap Instant.parse in toDateTime. Use DateTime.parse directly.",
PresubmitCheck(
r".*toInstant\(\s*DateTime\.parse\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap DateTime.parse in toInstant. Use Instant.parse directly.",
PresubmitCheck(
r".*cloneProjectedAtTime\(\s*toDateTime\(.*",
"java",
{},
):
"Do not use cloneProjectedAtTime(toDateTime(...)). Use cloneProjectedAtTime(...) instead.",
"Do not use java.time.ZonedDateTime. Use java.time.OffsetDateTime per go/avoid-zdt.",
PresubmitCheck(
r".*ZoneId\.of\(\s*\"UTC\"\s*\).*",
"java",
{},
):
"Do not use ZoneId.of(\"UTC\"). Use java.time.ZoneOffset.UTC."
"Do not use ZoneId.of(\"UTC\"). Use java.time.ZoneOffset.UTC.",
PresubmitCheck(
r".*org\.joda\.time.*",
"java",
{"SafeBrowsingTransforms.java"},
):
"Do not use Joda-Time. Use java.time instead.",
}
# Note that this regex only works for one kind of Flyway file. If we want to

View File

@@ -39,9 +39,9 @@ task runConsoleWebappUnitTests(type: Exec) {
task buildConsoleWebapp(type: Exec) {
workingDir "${consoleDir}/"
executable 'npm'
executable 'npx'
def configuration = project.getProperty('configuration')
args 'run', "build", "--configuration=${configuration}"
args 'ng', 'build', '--base-href=/console/', "--configuration=${configuration}", "--output-path=staged/dist"
doFirst {
println "Building console for environment: ${configuration}"
}
@@ -52,8 +52,8 @@ task buildConsoleForAll() {}
def createConsoleTask = { env ->
project.tasks.register("buildConsoleFor${env.capitalize()}", Exec) {
workingDir "${consoleDir}/"
executable 'npm'
args 'run', 'build', "--configuration=${env}"
executable 'npx'
args 'ng', 'build', '--base-href=/console/', "--configuration=${env}"
doFirst {
println "Building console for environment: ${env}"
}
@@ -107,3 +107,4 @@ tasks.applyFormatting.dependsOn(tasks.npmInstallDeps)
tasks.checkFormatting.dependsOn(tasks.npmInstallDeps)
tasks.build.dependsOn(tasks.checkFormatting)
tasks.build.dependsOn(tasks.runConsoleWebappUnitTests)
tasks.build.dependsOn(tasks.buildConsoleForAll)

View File

@@ -629,15 +629,15 @@
}
},
"node_modules/@angular/build/node_modules/@types/node": {
"version": "25.6.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.6.0.tgz",
"integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
"version": "25.9.1",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.9.1.tgz",
"integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"undici-types": "~7.19.0"
"undici-types": ">=7.24.0 <7.24.7"
}
},
"node_modules/@angular/build/node_modules/@vitejs/plugin-basic-ssl": {
@@ -744,9 +744,9 @@
}
},
"node_modules/@angular/build/node_modules/undici-types": {
"version": "7.19.2",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.19.2.tgz",
"integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
"version": "7.24.6",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT",
"optional": true,

View File

@@ -23,7 +23,11 @@ import { MaterialModule } from './material.module';
import { BackendService } from './shared/services/backend.service';
import { provideHttpClient } from '@angular/common/http';
import {
HttpClientXsrfModule,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { BillingInfoComponent } from './billingInfo/billingInfo.component';
import {
@@ -118,6 +122,10 @@ export class SelectedRegistrarModule {}
MaterialModule,
SelectedRegistrarModule,
SnackBarModule,
HttpClientXsrfModule.withOptions({
cookieName: 'X-CSRF-Token',
headerName: 'X-CSRF-Token',
}),
],
providers: [
BackendService,
@@ -130,7 +138,7 @@ export class SelectedRegistrarModule {}
subscriptSizing: 'dynamic',
},
},
provideHttpClient(),
provideHttpClient(withInterceptorsFromDi()),
],
})
export class AppModule {}

View File

@@ -53,14 +53,7 @@ def dockerIncompatibleTestPatterns = [
// affected by global states outside of Nomulus classes, e.g., threads and
// objects retained by frameworks.
// TODO(weiminyu): identify cause and fix offending tests.
def fragileTestPatterns = [
// Breaks random other tests when running with standardTests.
"google/registry/bsa/UploadBsaUnavailableDomainsActionTest.*",
// Currently changes a global configuration parameter that for some reason
// results in timestamp inversions for other tests. TODO(mmuller): fix.
"google/registry/flows/host/HostInfoFlowTest.*",
"google/registry/beam/common/RegistryPipelineWorkerInitializerTest.*",
] + dockerIncompatibleTestPatterns
def fragileTestPatterns = dockerIncompatibleTestPatterns
sourceSets {
main {
@@ -94,7 +87,6 @@ processTestResources {
configurations {
jaxb
soy
devtool
nonprodImplementation.extendsFrom implementation
@@ -120,7 +112,7 @@ configurations {
// For reasons we do not understand, marking the following dependencies as
// compileOnly instead of compile does not exclude them from runtimeClasspath.
all {
// servlet-api:3.1 pulled in but not used by soy compiler
// servlet-api:3.1 pulled in but not used
exclude group: 'javax.servlet', module: 'javax.servlet-api'
}
}
@@ -166,10 +158,6 @@ dependencies {
implementation deps['com.google.flogger:flogger']
implementation deps['com.google.guava:guava']
implementation deps['com.google.protobuf:protobuf-java']
// Might need to add this back if we re-add nebula-lint
// gradleLint.ignore('unused-dependency') {
implementation deps['com.google.gwt:gwt-user']
// }
implementation deps['com.google.cloud:google-cloud-compute']
implementation deps['com.google.cloud:google-cloud-core']
implementation deps['com.google.cloud:google-cloud-storage']
@@ -181,9 +169,8 @@ dependencies {
implementation deps['com.google.oauth-client:google-oauth-client-jetty']
implementation deps['com.google.oauth-client:google-oauth-client-servlet']
implementation deps['com.google.re2j:re2j']
implementation deps['com.google.template:soy']
implementation deps['com.googlecode.json-simple:json-simple']
implementation deps['com.jcraft:jsch']
implementation deps['org.freemarker:freemarker']
implementation deps['com.github.mwiede:jsch']
implementation deps['com.zaxxer:HikariCP']
implementation deps['com.squareup.okhttp3:okhttp']
implementation deps['dnsjava:dnsjava']
@@ -198,7 +185,6 @@ dependencies {
implementation deps['jakarta.persistence:jakarta.persistence-api']
implementation deps['jakarta.servlet:jakarta.servlet-api']
implementation deps['jakarta.xml.bind:jakarta.xml.bind-api']
implementation deps['joda-time:joda-time']
implementation deps['org.antlr:antlr4']
implementation deps['org.antlr:antlr4-runtime']
implementation deps['org.apache.avro:avro']
@@ -287,6 +273,7 @@ dependencies {
testImplementation deps['org.junit-pioneer:junit-pioneer']
testImplementation deps['org.junit.platform:junit-platform-runner']
testImplementation deps['org.junit.platform:junit-platform-suite-api']
testImplementation deps['org.junit.platform:junit-platform-suite']
testImplementation deps['org.mockito:mockito-core']
testImplementation deps['org.mockito:mockito-junit-jupiter']
@@ -300,9 +287,6 @@ dependencies {
jaxb deps['org.glassfish.jaxb:jaxb-runtime']
jaxb deps['org.glassfish.jaxb:jaxb-xjc']
// Dependency needed for soy to java compilation.
soy deps['com.google.template:soy']
// Flyway classes needed to generate the golden file.
implementation deps['org.flywaydb:flyway-core']
implementation deps['org.flywaydb:flyway-database-postgresql']
@@ -372,62 +356,7 @@ task jaxbToJava {
}
}
task soyToJava {
// Relative paths of soy directories.
def spec11SoyDir = "google/registry/reporting/spec11/soy"
def toolsSoyDir = "google/registry/tools/soy"
def soyRelativeDirs = [spec11SoyDir, toolsSoyDir]
soyRelativeDirs.each {
inputs.dir "${resourcesSourceDir}/${it}"
outputs.dir "${generatedDir}/${it}"
}
ext.soyToJava = { javaPackage, outputDirectory, soyFiles ->
project.services.get(ExecOperations).javaexec {
mainClass = "com.google.template.soy.SoyParseInfoGenerator"
classpath = configurations.soy
jvmArgs = ["--sun-misc-unsafe-memory-access=allow", "--enable-native-access=ALL-UNNAMED"]
args = ["--javaPackage", "${javaPackage}",
"--outputDirectory", "${outputDirectory}",
"--javaClassNameSource", "filename",
"--srcs", "${soyFiles.join(',')}"]
}
// Replace the "@link" tags after the "@deprecated" tags in the generated
// files. The soy compiler doesn't generate imports for these, causing
// us to get warnings when we generate javadocs.
// TODO(b/200296387): To be fair, the deprecations are accurate: we're
// using the old "SoyInfo" classes instead of the new "Templates" files.
// When we convert to the new classes, this hack can go away.
def outputs = fileTree(outputDirectory) {
include '**/*.java'
}
outputs.each { file ->
project.services.get(ExecOperations).exec {
commandLine = ['sed', '-i""', '-e', 's/@link/LINK/g', file.getCanonicalPath()]
}
}
}
doLast {
soyToJava('google.registry.tools.soy',
"${generatedDir}/${toolsSoyDir}",
fileTree(
dir: "${resourcesSourceDir}/${toolsSoyDir}",
include: ['**/*.soy']))
soyToJava('google.registry.reporting.spec11.soy',
"${generatedDir}/${spec11SoyDir}",
fileTree(
dir: "${resourcesSourceDir}/${spec11SoyDir}",
include: ['**/*.soy']))
}
}
compileJava.dependsOn jaxbToJava
compileJava.dependsOn soyToJava
// Make testing artifacts available to be depended up on by other projects.
// TODO: factor out google.registry.testing to be a separate project.
@@ -479,7 +408,6 @@ Optional<List<String>> getToolArgsList() {
return Optional.empty()
}
// To run the nomulus tools with these command line tokens:
// "--foo", "bar baz", "--qux=quz"
// gradle core:registryTool --args="--foo 'bar baz' --qux=quz"
@@ -514,7 +442,7 @@ project.tasks.create('generateSqlSchema', JavaExec) {
mainClass = 'google.registry.tools.DevTool'
jvmArgs "--sun-misc-unsafe-memory-access=allow"
args = [
'-e', 'alpha',
'-e', 'unittest',
'generate_sql_schema', '--start_postgresql', '-o',
"${rootProject.projectRootDir}/db/src/main/resources/sql/schema/" +
"db-schema.sql.generated"
@@ -766,10 +694,7 @@ task fragileTest(type: FilteringTest) {
// Dedicated test suite for schema-dependent tests.
task sqlIntegrationTest(type: FilteringTest) {
// TestSuite still requires a JUnit 4 runner, which knows how to handle JUnit 5 tests.
// Here we need to override parent's choice of JUnit 5. If changing this, remember to
// change :integration:sqlIntegrationTest too.
useJUnit()
useJUnitPlatform()
excludeTestCases = false
tests = ['google/registry/schema/integration/SqlIntegrationTestSuite.*']
@@ -816,14 +741,9 @@ test {
// Don't run any tests from this task, all testing gets done in the
// FilteringTest tasks.
exclude "**"
// TODO(weiminyu): Remove dependency on sqlIntegrationTest
}.dependsOn(fragileTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
}.dependsOn(standardTest, registryToolIntegrationTest, sqlIntegrationTest, fragileTest)
// When we override tests, we also break the cleanTest command.
cleanTest.dependsOn(cleanFragileTest, cleanStandardTest,
cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest)
cleanTest.dependsOn(cleanStandardTest, cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest, cleanFragileTest)
project.build.dependsOn devtool
project.build.dependsOn buildToolImage
project.build.dependsOn ':stage'
project.build.dependsOn devtool, buildToolImage

View File

@@ -1,21 +1,19 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
aopalliance:aopalliance:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.21=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.20.2=testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.woodstox:woodstox-core:7.0.0=testCompileClasspath,testRuntimeClasspath
com.fasterxml:classmate:1.7.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.woodstox:woodstox-core:7.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.2.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.2.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-api:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport-zerodep:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -28,6 +26,7 @@ com.github.jnr:jnr-posix:3.1.22=compileClasspath,deploy_jar,nonprodCompileClassp
com.github.jnr:jnr-unixsocket:0.38.25=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.mwiede:jsch:2.28.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api-client:google-api-client-jackson2:2.7.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -35,60 +34,64 @@ com.google.api-client:google-api-client-java6:2.1.4=compileClasspath,deploy_jar,
com.google.api-client:google-api-client-servlet:2.7.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-servlet:2.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api-client:google-api-client:2.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.68.0=testCompileClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.196.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.196.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.130.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.132.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-control-v2:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.65.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.68.0=testCompileClasspath
com.google.api.grpc:grpc-google-common-protos:2.67.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.196.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.196.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta:3.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-compute-v1:1.82.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.125.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.75.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-compute-v1:1.102.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.128.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-logging-v2:0.118.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.85.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.130.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.132.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.51.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.92.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.92.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.51.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.92.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-control-v2:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.141.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.141.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-common-protos:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.60.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.65.0=testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.57.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:api-common:2.62.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-grpc:2.79.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-httpjson:2.79.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20260227-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.51.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.92.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.141.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.182.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.141.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.182.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-common-protos:2.71.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.62.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.63.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.80.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.80.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.80.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20260522-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-rev20251012-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20250606-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20260405-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260402-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260405-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260413-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20260503-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260421-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260428-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260525-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-groupssettings:v1-rev20220614-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-iam:v2-rev20250502-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -96,11 +99,10 @@ com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileC
com.google.apis:google-api-services-monitoring:v3-rev20260129-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sheets:v4-rev20260213-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20260317-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20251118-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.apis:google-api-services-storage:v1-rev20260204-2.0.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20260510-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20260204-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.0.1=nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service:1.1.1=annotationProcessor
@@ -111,78 +113,70 @@ com.google.auto:auto-common:1.2.2=annotationProcessor,nonprodAnnotationProcessor
com.google.cloud.bigdataoss:gcsio:2.2.26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigdataoss:util:2.2.26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.datastore:datastore-v1-proto-client:2.34.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.datastore:datastore-v1-proto-client:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:exporter-metrics:0.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:shared-resourcemapping:0.33.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.28.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.28.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.28.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.28.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:3.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-compute:1.82.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-grpc:2.69.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.54.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-http:2.69.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-compute:1.102.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-grpc:2.70.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.70.0=testCompileClasspath
com.google.cloud:google-cloud-core:2.66.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core:2.70.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-logging:3.29.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:3.85.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.131.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.148.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-spanner:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.127.24=testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.132.0=testCompileClasspath
com.google.cloud:google-cloud-pubsub:1.150.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.51.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.92.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-spanner:6.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage-control:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.68.0=testCompileClasspath
com.google.cloud:google-cloud-tasks:2.51.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.92.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:grpc-gcp:1.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:libraries-bom:26.48.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.10.1=soy
com.google.code.gson:gson:2.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.common.html.types:types:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.dagger:dagger-compiler:2.59.2=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger-spi:2.59.2=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger:2.59.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.devtools.ksp:symbol-processing-api:2.2.20-2.0.3=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.20.0=soy
com.google.errorprone:error_prone_annotations:2.36.0=checkstyle
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.escapevelocity:escapevelocity:1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flatbuffers:flatbuffers-java:24.3.25=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.1=soy
com.google.guava:failureaccess:1.0.3=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-parent:32.1.1-jre=soy
com.google.guava:guava-testlib:33.3.0-jre=testRuntimeClasspath
com.google.guava:guava-testlib:33.6.0-jre=testCompileClasspath
com.google.guava:guava:32.1.1-jre=soy
com.google.guava:guava:33.4.8-jre=checkstyle
com.google.guava:guava:33.5.0-jre=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.6.0-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-apache-v2:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.http-client:google-http-client-apache-v2:2.1.0=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:1.46.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.http-client:google-http-client-appengine:2.1.0=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-apache-v2:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-gson:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:1.46.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.http-client:google-http-client-jackson2:2.1.0=testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-protobuf:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:7.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:3.0.0=checkstyle
com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.jsinterop:jsinterop-annotations:1.0.1=soy
com.google.jsinterop:jsinterop-annotations:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:contrib:1.0.7=testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:metrics:1.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:stackdriver:1.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -193,25 +187,21 @@ com.google.oauth-client:google-oauth-client-jetty:1.39.0=compileClasspath,nonpro
com.google.oauth-client:google-oauth-client-servlet:1.36.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-servlet:1.39.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.oauth-client:google-oauth-client:1.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:4.33.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.protobuf:protobuf-java-util:4.35.0-RC1=testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.21.7=soy
com.google.protobuf:protobuf-java-util:4.33.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:4.35.0-RC1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:4.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2024-02-26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.truth:truth:1.4.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.jcraft:jsch:0.1.55=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.lmax:disruptor:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.puppycrawl.tools:checkstyle:10.24.0=checkstyle
com.squareup.okhttp3:okhttp:4.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okhttp3:okhttp-jvm:5.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okhttp3:okhttp:5.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-bom:3.0.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.okio:okio-fakefilesystem-jvm:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-fakefilesystem:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-jvm:3.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio:3.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-jvm:3.16.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio:3.16.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-compiler:4.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-grpc-server-generator:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.wire:wire-grpc-server:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -228,8 +218,8 @@ com.squareup:kotlinpoet:1.11.0=annotationProcessor,testAnnotationProcessor
com.squareup:kotlinpoet:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-runtime:4.1.2=deploy_jar,jaxb,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-tools:4.1.2=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.7=jaxb
com.sun.xml.bind.external:rngom:4.0.7=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.9=jaxb
com.sun.xml.bind.external:rngom:4.0.9=jaxb
com.sun.xml.dtd-parser:dtd-parser:1.5.1=jaxb
com.zaxxer:HikariCP:7.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-beanutils:commons-beanutils:1.10.1=checkstyle
@@ -238,7 +228,7 @@ commons-codec:commons-codec:1.19.0=compileClasspath,deploy_jar,nonprodCompileCla
commons-collections:commons-collections:3.2.2=checkstyle
commons-io:commons-io:2.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-logging:commons-logging:1.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
dnsjava:dnsjava:3.6.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
dnsjava:dnsjava:3.6.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0=testRuntimeClasspath
@@ -251,44 +241,33 @@ io.apicurio:apicurio-registry-protobuf-schema-utilities:3.0.0.M2=compileClasspat
io.github.classgraph:classgraph:4.8.162=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.16=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.java-diff-utils:java-diff-utils:4.17=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.ss-bhatt:testcontainers-valkey:1.0.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-alts:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-api:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-auth:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-context:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-core:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-googleapis:1.80.0=testRuntimeClasspath
io.grpc:grpc-grpclb:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-grpclb:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-inprocess:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-netty-shaded:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-opentelemetry:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf-lite:1.80.0=testRuntimeClasspath
io.grpc:grpc-protobuf:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-rls:1.80.0=testRuntimeClasspath
io.grpc:grpc-services:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-services:1.80.0=testRuntimeClasspath
io.grpc:grpc-stub:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-stub:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-util:1.80.0=testRuntimeClasspath
io.grpc:grpc-xds:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-xds:1.80.0=testRuntimeClasspath
io.grpc:grpc-alts:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.76.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.81.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-grpclb:1.76.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-grpclb:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.76.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.76.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-opentelemetry:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.81.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.76.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-rls:1.81.0=testRuntimeClasspath
io.grpc:grpc-services:1.76.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-services:1.81.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-stub:1.81.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.76.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-util:1.81.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-xds:1.76.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-xds:1.81.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-buffer:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -313,33 +292,33 @@ io.opencensus:opencensus-exporter-metrics-util:0.31.0=compileClasspath,deploy_ja
io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-impl-core:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-impl:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.contrib:opentelemetry-gcp-resources:1.37.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry.contrib:opentelemetry-gcp-resources:1.45.0-alpha=testCompileClasspath,testRuntimeClasspath
io.opentelemetry.contrib:opentelemetry-gcp-resources:1.37.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry.contrib:opentelemetry-gcp-resources:1.45.0-alpha=testCompileClasspath
io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:2.1.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.1.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.semconv:opentelemetry-semconv:1.29.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-api:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-bom:1.42.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-common:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-common:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-context:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-extension-incubator:1.35.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.62.0=testCompileClasspath,testRuntimeClasspath
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.protostuff:protostuff-api:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -348,26 +327,27 @@ io.protostuff:protostuff-core:1.8.0=compileClasspath,deploy_jar,nonprodCompileCl
io.protostuff:protostuff-runtime:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.1.4=jaxb
jakarta.activation:jakarta.activation-api:2.2.0-M1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.2.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.2.0-M2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.mail:jakarta.mail-api:2.2.0-M1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.persistence:jakarta.persistence-api:3.2.0=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.servlet:jakarta.servlet-api:6.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.servlet:jakarta.servlet-api:6.0.0=testCompileClasspath,testRuntimeClasspath
jakarta.servlet:jakarta.servlet-api:6.2.0-M2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
jakarta.transaction:jakarta.transaction-api:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=compileClasspath,jaxb,nonprodCompileClasspath,testCompileClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=jaxb
jakarta.xml.bind:jakarta.xml.bind-api:4.1.0-M1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.annotation:jsr250-api:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.validation:validation-api:1.0.0.GA=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
joda-time:joda-time:2.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
junit:junit:4.13.2=nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
net.arnx:nashorn-promise:0.1.1=testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.17.7=compileClasspath,nonprodCompileClasspath
net.bytebuddy:byte-buddy:1.17.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
net.bytebuddy:byte-buddy:1.18.8-jdk5=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.8-jdk5=testCompileClasspath
net.java.dev.jna:jna:5.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
net.sf.saxon:Saxon-HE:12.5=checkstyle
@@ -380,24 +360,24 @@ org.apache.arrow:arrow-format:17.0.0=compileClasspath,deploy_jar,nonprodCompileC
org.apache.arrow:arrow-memory-core:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-vector:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.avro:avro:1.11.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-construction-java:2.54.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-java:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-direct-java:2.72.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-java-fn-execution:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-core:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-expansion-service:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-arrow:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-avro:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-protobuf:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-java:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-direct-java:2.73.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-java-fn-execution:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-core:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-expansion-service:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-arrow:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-avro:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-protobuf:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-fn-execution:2.54.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-harness:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-transform-service-launcher:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-harness:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-transform-service-launcher:2.73.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_60_1:0.1=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_69_0:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -407,7 +387,7 @@ org.apache.commons:commons-exec:1.3=testRuntimeClasspath
org.apache.commons:commons-lang3:3.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.apache.commons:commons-lang3:3.20.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.8.1=checkstyle
org.apache.commons:commons-pool2:2.12.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-pool2:2.13.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-text:1.15.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-text:1.3=checkstyle
org.apache.ftpserver:ftplet-api:1.2.1=testCompileClasspath,testRuntimeClasspath
@@ -424,84 +404,81 @@ org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle
org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle
org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle
org.apache.mina:mina-core:2.2.4=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-common:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.21=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-common:3.0.0-M4=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:3.0.0-M4=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:3.0.0-M4=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:3.0.0-M4=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.22=testCompileClasspath,testRuntimeClasspath
org.apache.xbean:xbean-reflect:3.7=checkstyle
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.bouncycastle:bcpg-jdk18on:1.84=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcpkix-jdk18on:1.84=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcprov-jdk18on:1.84=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcutil-jdk18on:1.84=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-compat-qual:2.5.3=annotationProcessor,compileClasspath,nonprodCompileClasspath,soy,testAnnotationProcessor,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.3=annotationProcessor,compileClasspath,nonprodCompileClasspath,testAnnotationProcessor,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.19.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
org.checkerframework:checker-qual:3.33.0=soy
org.checkerframework:checker-qual:3.49.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
org.checkerframework:checker-qual:3.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.49.3=checkstyle
org.checkerframework:checker-qual:3.52.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.24=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.26=testCompileClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.27=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.codehaus.plexus:plexus-classworlds:2.6.0=checkstyle
org.codehaus.plexus:plexus-component-annotations:2.1.0=checkstyle
org.codehaus.plexus:plexus-container-default:2.1.0=checkstyle
org.codehaus.plexus:plexus-utils:3.3.0=checkstyle
org.codehaus.woodstox:stax2-api:4.2.2=testCompileClasspath,testRuntimeClasspath
org.codehaus.woodstox:stax2-api:4.2.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.angus:angus-activation:2.0.3=jaxb
org.eclipse.angus:angus-activation:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.angus:jakarta.mail:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee:jetty-ee-webapp:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.8=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.7=jaxb
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee:jetty-ee-webapp:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.9=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.freemarker:freemarker:2.3.34=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.9=jaxb
org.glassfish.jaxb:jaxb-core:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-core:4.0.7=jaxb
org.glassfish.jaxb:jaxb-core:4.0.9=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-runtime:4.0.7=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.7=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.9=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.9=jaxb
org.glassfish.jaxb:txw2:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:txw2:4.0.7=jaxb
org.glassfish.jaxb:xsom:4.0.7=jaxb
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:txw2:4.0.9=jaxb
org.glassfish.jaxb:xsom:4.0.9=jaxb
org.hamcrest:hamcrest-core:1.3=nonprodCompileClasspath,nonprodRuntimeClasspath
org.hamcrest:hamcrest-core:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-library:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest:2.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.hamcrest:hamcrest:3.0=testCompileClasspath,testRuntimeClasspath
org.hibernate.models:hibernate-models:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.models:hibernate-models:1.1.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jacoco:org.jacoco.agent:0.8.14=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.14=jacocoAnt
org.jacoco:org.jacoco.core:0.8.14=jacocoAnt
org.jacoco:org.jacoco.report:0.8.14=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.jboss.logging:jboss-logging:3.6.1.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jcommander:jcommander:2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jboss.logging:jboss-logging:3.6.3.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jcommander:jcommander:3.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-bom:1.4.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-metadata-jvm:2.2.20=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-reflect:1.6.10=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-reflect:1.9.20=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:2.2.21=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:2.2.20=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib:2.2.21=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -510,67 +487,63 @@ org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.0.1=deploy_jar,nonprodRun
org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jline:jline:3.30.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jline:jline:4.1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.joda:joda-money:2.0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.json:json:20230618=soy
org.json:json:20251224=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.json:json:20260522=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jsoup:jsoup:1.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jspecify:jspecify:1.0.0=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
org.junit-pioneer:junit-pioneer:2.3.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-migrationsupport:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.13.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-migrationsupport:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.14.4=testRuntimeClasspath
org.junit:junit-bom:5.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-engine:6.1.0=testRuntimeClasspath
org.junit.platform:junit-platform-suite:6.1.0=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:6.1.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.23.0=testCompileClasspath,testRuntimeClasspath
org.objenesis:objenesis:3.3=testRuntimeClasspath
org.ogce:xpp3:1.1.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-analysis:9.5=soy
org.ow2.asm:asm-analysis:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.5=soy
org.ow2.asm:asm-commons:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.9=jacocoAnt
org.ow2.asm:asm-tree:9.5=soy
org.ow2.asm:asm-tree:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-tree:9.9=jacocoAnt
org.ow2.asm:asm-util:9.5=soy
org.ow2.asm:asm-util:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.5=soy
org.ow2.asm:asm:9.7.1=compileClasspath,nonprodCompileClasspath
org.ow2.asm:asm:9.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.9=jacocoAnt
org.pcollections:pcollections:4.0.1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
org.postgresql:postgresql:42.7.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.postgresql:postgresql:42.7.11=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.reflections:reflections:0.10.2=checkstyle
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v145:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v146:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v147:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v146:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v147:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v148:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.44.0=testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.36=testCompileClasspath,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.18=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-jdk14:2.0.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.testcontainers:database-commons:1.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -580,23 +553,22 @@ org.testcontainers:postgresql:1.21.4=compileClasspath,deploy_jar,nonprodCompileC
org.testcontainers:selenium:1.21.4=testCompileClasspath,testRuntimeClasspath
org.testcontainers:testcontainers:1.21.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.threeten:threetenbp:1.7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
org.xerial.snappy:snappy-java:1.1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.xmlresolver:xmlresolver:5.2.2=checkstyle
org.yaml:snakeyaml:2.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.yaml:snakeyaml:2.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
redis.clients.authentication:redis-authx-core:0.1.1-beta2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
redis.clients:jedis:7.4.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
redis.clients:jedis:8.0.0-beta1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson.core:jackson-core:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson.core:jackson-databind:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson:jackson-bom:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-api:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-tools:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-utility:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=devtool,shadow

View File

@@ -54,9 +54,15 @@ public class BatchModule {
static final int DEFAULT_MAX_QPS = 10;
@Provides
@Parameter("url")
static String provideUrl(HttpServletRequest req) {
return extractRequiredParameter(req, "url");
@Parameter("replyTo")
static String provideReplyTo(HttpServletRequest req) {
return extractRequiredParameter(req, "replyTo");
}
@Provides
@Parameter("receiver")
static String provideReceiver(HttpServletRequest req) {
return extractRequiredParameter(req, "receiver");
}
@Provides

View File

@@ -16,30 +16,35 @@ package google.registry.batch;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.services.gmail.Gmail;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import dagger.Lazy;
import google.registry.config.RegistryConfig.Config;
import google.registry.groups.GmailClient;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.UrlConnectionService;
import google.registry.request.UrlConnectionUtils;
import google.registry.request.auth.Auth;
import google.registry.util.EmailMessage;
import google.registry.util.Retrier;
import jakarta.inject.Inject;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.util.Optional;
/**
* Action that executes a canned script specified by the caller.
*
* <p>This class provides a hook for invoking hard-coded methods. The main use case is to verify in
* Sandbox and Production environments new features that depend on environment-specific
* configurations. For example, the {@code DelegatedCredential}, which requires correct GWorkspace
* configuration, has been tested this way. Since it is a hassle to add or remove endpoints, we keep
* this class all the time.
* configurations.
*
* <p>This action can be invoked using the Nomulus CLI command: {@code nomulus -e ${env} curl
* --service BACKEND -X POST -u '/_dr/task/executeCannedScript}'}
* --service BACKEND -X POST -d 'sender=sender@example.com' -d 'receiver=receiver@example.com' -u
* '/_dr/task/executeCannedScript'}
*/
@Action(
service = Action.Service.BACKEND,
@@ -50,39 +55,69 @@ import javax.net.ssl.HttpsURLConnection;
public class CannedScriptExecutionAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Inject UrlConnectionService urlConnectionService;
@Inject Lazy<Gmail> gmail;
@Inject Retrier retrier;
@Inject
@Config("isEmailSendingEnabled")
boolean isEmailSendingEnabled;
@Inject Response response;
@Inject
@Parameter("url")
String url;
@Parameter("replyTo")
String replyTo;
@Inject
@Parameter("receiver")
String receiver;
@Config("invoiceReplyToEmailAddress")
Optional<InternetAddress> replyToEmailAddressFromConfig;
@Inject
CannedScriptExecutionAction() {}
@Override
public void run() {
Integer responseCode = null;
String responseContent = null;
// For b/510340944, validating a new G Workspace user can send email. Code below can be
// removed or changed afterward.
try {
logger.atInfo().log("Connecting to: %s", url);
HttpsURLConnection connection =
(HttpsURLConnection) urlConnectionService.createConnection(new URL(url));
responseCode = connection.getResponseCode();
logger.atInfo().log("Code: %d", responseCode);
logger.atInfo().log("Headers: %s", connection.getHeaderFields());
responseContent = new String(UrlConnectionUtils.getResponseBytes(connection), UTF_8);
logger.atInfo().log("Response: %s", responseContent);
logger.atInfo().log("Sending email to %s with replyTo %s", receiver, replyTo);
GmailClient gmailClient =
new GmailClient(gmail, retrier, isEmailSendingEnabled, new InternetAddress(replyTo));
gmailClient.sendEmail(
EmailMessage.newBuilder()
.addRecipient(new InternetAddress(receiver))
.setSubject(String.format("Email with manually set replyTo header %s", replyTo))
.setBody("See subject")
.build());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setSubject(
String.format(
"Email with injected replyTo header %s", replyToEmailAddressFromConfig))
.setBody("See header")
.setRecipients(ImmutableList.of(new InternetAddress(receiver)))
.setReplyToEmailAddress(replyToEmailAddressFromConfig)
.setContentType(MediaType.HTML_UTF_8)
.build());
response.setPayload("Emails sent successfully.");
} catch (AddressException e) {
logger.atWarning().withCause(e).log(
"Invalid email address: sender=%s, receiver=%s", replyTo, receiver);
response.setStatus(400);
response.setPayload("Invalid email address provided.");
} catch (Exception e) {
logger.atWarning().withCause(e).log("Connection to %s failed", url);
logger.atSevere().withCause(e).log("Failed to send email");
throw new RuntimeException(e);
} finally {
if (responseCode != null) {
response.setStatus(responseCode);
}
if (responseContent != null) {
response.setPayload(responseContent);
}
}
}
}

View File

@@ -92,7 +92,7 @@ public class DeleteProberDataAction implements Runnable {
// prevents accidental double-map with the same key from immediately deleting active domains)
//
// Note: creationTime must be compared to a Java object (CreateAutoTimestamp) but deletionTime can
// be compared directly to the SQL timestamp (it's a DateTime)
// be compared directly to the SQL timestamp (it's an Instant)
private static final String DOMAIN_QUERY_STRING =
"FROM Domain d WHERE d.tld IN :tlds AND d.domainName NOT LIKE 'nic.%%' AND"
+ " (d.subordinateHosts IS NULL OR array_length(d.subordinateHosts) = 0) AND"

View File

@@ -39,8 +39,8 @@ import org.jetbrains.annotations.NotNull;
* A record representing a single billable event, parsed from a {@code SchemaAndRecord}.
*
* @param id The unique ID for the {@code BillingEvent} associated with this event.
* @param billingTime The DateTime (in UTC) this event becomes billable.
* @param eventTime The DateTime (in UTC) this event was generated.
* @param billingTime The Instant (in UTC) this event becomes billable.
* @param eventTime The Instant (in UTC) this event was generated.
* @param registrarId The billed registrar's name.
* @param billingId The billed registrar's billing account key.
* @param poNumber The Purchase Order number.
@@ -225,7 +225,6 @@ public record BillingEvent(
"UnitPriceCurrency",
"PONumber");
/** Generates the CSV header for the overall invoice. */
static String invoiceHeader() {
return Joiner.on(",").join(INVOICE_HEADERS);

View File

@@ -22,12 +22,10 @@ import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import java.io.Serializable;
import java.time.Instant;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
/** Interface for query instances used by {@link RegistryJpaIO.Read}. */
public interface RegistryQuery<T> extends Serializable {
@@ -61,11 +59,7 @@ public interface RegistryQuery<T> extends Serializable {
if (parameters != null) {
parameters.forEach(
(key, value) -> {
if (value instanceof DateTime dt) {
query.setParameter(key, Instant.ofEpochMilli(dt.getMillis()));
} else {
query.setParameter(key, value);
}
query.setParameter(key, value);
});
}
JpaTransactionManager.setQueryFetchSize(query, QUERY_FETCH_SIZE);

View File

@@ -212,12 +212,14 @@ public class RdeIO {
}
}
// Don't write the IDN elements for BRDA.
// Don't write the IDN elements or EPP params for BRDA.
if (mode == RdeMode.FULL) {
for (IdnTableEnum idn : IdnTableEnum.values()) {
output.write(marshaller.marshalIdn(idn.getTable()));
counter.increment(RdeResourceType.IDN);
}
output.write(marshaller.marshalRdeEppParams());
counter.increment(RdeResourceType.EPP_PARAMS);
}
// Output XML that says how many resources were emitted.

View File

@@ -21,7 +21,6 @@ import static google.registry.beam.rde.RdePipeline.TupleTags.DOMAIN_FRAGMENTS;
import static google.registry.beam.rde.RdePipeline.TupleTags.EXTERNAL_HOST_FRAGMENTS;
import static google.registry.beam.rde.RdePipeline.TupleTags.HOST_TO_PENDING_DEPOSIT;
import static google.registry.beam.rde.RdePipeline.TupleTags.PENDING_DEPOSIT;
import static google.registry.beam.rde.RdePipeline.TupleTags.REFERENCED_CONTACTS;
import static google.registry.beam.rde.RdePipeline.TupleTags.REFERENCED_HOSTS;
import static google.registry.beam.rde.RdePipeline.TupleTags.REVISION_ID;
import static google.registry.beam.rde.RdePipeline.TupleTags.SUPERORDINATE_DOMAINS;
@@ -131,9 +130,8 @@ import org.apache.beam.sdk.values.TypeDescriptor;
*
* After the most recent (live) domain resources are loaded from the corresponding history objects,
* we marshall them to deposit fragments and emit the (pending deposit: deposit fragment) pairs for
* further processing. We also find all the contacts and hosts referenced by a given domain and emit
* pairs of (contact/host repo ID: pending deposit) for all RDE pending deposits for further
* processing.
* further processing. We also find all the hosts referenced by a given domain and emit pairs of
* (host repo ID: pending deposit) for all RDE pending deposits for further processing.
*
* <h3>{@link Host}</h3>
*
@@ -358,7 +356,6 @@ public class RdePipeline implements Serializable {
private <T extends HistoryEntry> EppResource loadResourceByHistoryEntryId(
Class<T> historyEntryClazz, String repoId, long revisionId) {
return tm().transact(
() ->
tm().loadByKey(
@@ -372,10 +369,10 @@ public class RdePipeline implements Serializable {
* Remove unreferenced resources by joining the (repoId, pendingDeposit) pair with the (repoId,
* revisionId) on the repoId.
*
* <p>The (repoId, pendingDeposit) pairs denote resources (contact, host) that are referenced from
* a domain, that are to be included in the corresponding pending deposit.
* <p>The (repoId, pendingDeposit) pairs denote hosts that are referenced from a domain, that are
* to be included in the corresponding pending deposit.
*
* <p>The (repoId, revisionId) paris come from the most recent history entry query, which can be
* <p>The (repoId, revisionId) pairs come from the most recent history entry query, which can be
* used to load the embedded resources themselves.
*
* @return a pair of (repoId, ([pendingDeposit], [revisionId])) where neither the pendingDeposit
@@ -423,7 +420,7 @@ public class RdePipeline implements Serializable {
Counter domainFragmentCounter = Metrics.counter("RDE", "DomainFragment");
Counter referencedHostCounter = Metrics.counter("RDE", "ReferencedHost");
return domainHistories.apply(
"Map DomainHistory to DepositFragment " + "and emit referenced Contact and Host",
"Map DomainHistory to DepositFragment and emit referenced Host",
ParDo.of(
new DoFn<KV<String, Long>, KV<PendingDeposit, DepositFragment>>() {
@ProcessElement
@@ -465,8 +462,7 @@ public class RdePipeline implements Serializable {
});
}
})
.withOutputTags(
DOMAIN_FRAGMENTS, TupleTagList.of(REFERENCED_CONTACTS).and(REFERENCED_HOSTS)));
.withOutputTags(DOMAIN_FRAGMENTS, TupleTagList.of(REFERENCED_HOSTS)));
}
private PCollectionTuple processHostHistories(
@@ -627,9 +623,6 @@ public class RdePipeline implements Serializable {
protected static final TupleTag<KV<PendingDeposit, DepositFragment>> DOMAIN_FRAGMENTS =
new TupleTag<>() {};
protected static final TupleTag<KV<String, PendingDeposit>> REFERENCED_CONTACTS =
new TupleTag<>() {};
protected static final TupleTag<KV<String, PendingDeposit>> REFERENCED_HOSTS =
new TupleTag<>() {};

View File

@@ -14,7 +14,6 @@
package google.registry.beam.spec11;
import static google.registry.util.DateTimeUtils.toJodaInstant;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.http.HttpStatus.SC_OK;
@@ -132,7 +131,13 @@ public class SafeBrowsingTransforms {
if (!domainNameInfoBuffer.isEmpty()) {
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
results.forEach(
(kv) -> context.output(kv, toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
kv -> {
// The Apache Beam API requires org.joda.time.Instant here.
@SuppressWarnings("UnnecessarilyFullyQualified")
org.joda.time.Instant timestamp =
org.joda.time.Instant.ofEpochMilli(clock.nowMillis());
context.output(kv, timestamp, GlobalWindow.INSTANCE);
});
}
}

View File

@@ -68,6 +68,8 @@ public class BsaCredential {
private final Keyring keyring;
private final Gson gson;
private final Clock clock;
@Nullable private String authToken;
@@ -79,11 +81,13 @@ public class BsaCredential {
@Config("bsaAuthUrl") String authUrl,
@Config("bsaAuthTokenExpiry") Duration authTokenExpiry,
Keyring keyring,
Gson gson,
Clock clock) {
this.urlConnectionService = urlConnectionService;
this.authUrl = authUrl;
this.authTokenExpiry = authTokenExpiry;
this.keyring = keyring;
this.gson = gson;
this.clock = clock;
}
@@ -143,8 +147,7 @@ public class BsaCredential {
// TODO: catch json syntax exception
@SuppressWarnings("unchecked")
String idToken =
new Gson()
.fromJson(new String(getResponseBytes(connection), UTF_8), Map.class)
gson.fromJson(new String(getResponseBytes(connection), UTF_8), Map.class)
.getOrDefault(ID_TOKEN, "")
.toString();
if (idToken.isEmpty()) {

View File

@@ -114,11 +114,7 @@ public final class DownloadScheduler {
}
private boolean isTimeAgain(BsaDownload mostRecent, Duration interval) {
return mostRecent
.getCreationTime()
.plusMillis(interval.toMillis())
.minusMillis(CRON_JITTER.toMillis())
.isBefore(clock.now());
return mostRecent.getCreationTime().plus(interval).minus(CRON_JITTER).isBefore(clock.now());
}
/**

View File

@@ -0,0 +1,51 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import com.google.common.collect.ImmutableSet;
import com.google.monitoring.metrics.IncrementableMetric;
import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
/** Metrics tracking effectiveness of local and remote EPP resource caching. */
@Singleton
public class CacheMetrics {
public enum CacheHitType {
LOCAL,
REMOTE,
MISS,
MISS_NONEXISTENT
}
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
ImmutableSet.of(
LabelDescriptor.create("cache_name", "The type of the cache (domain/host)."),
LabelDescriptor.create("hit_type", "The type of cache hit or miss."));
private static final IncrementableMetric cacheLookups =
MetricRegistryImpl.getDefault()
.newIncrementableMetric(
"/cache/lookups", "Count of cache lookups", "count", LABEL_DESCRIPTORS);
@Inject
public CacheMetrics() {}
public void recordLookup(String cacheName, CacheHitType hitType) {
cacheLookups.increment(cacheName, hitType.toString());
}
}

View File

@@ -60,12 +60,15 @@ public final class CacheModule {
public static Optional<UnifiedJedis> provideJedis(
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
@Config("valkeyHostsAndPorts") Optional<ImmutableList<String>> valkeyHostsAndPorts,
@Config("valkeySslSocketFactory") SSLSocketFactory valkeySslSocketFactory) {
if (valkeyHostsAndPorts.map(ImmutableList::isEmpty).orElse(true)) {
@Config("valkeyCertificateAuthority") Optional<String> valkeyCertificateAuthority) {
if (valkeyHostsAndPorts.map(ImmutableList::isEmpty).orElse(true)
|| valkeyCertificateAuthority.isEmpty()) {
return Optional.empty();
}
ImmutableSet<HostAndPort> hostsAndPorts =
valkeyHostsAndPorts.get().stream().map(HostAndPort::from).collect(toImmutableSet());
SSLSocketFactory valkeySslSocketFactory =
createValkeySslSocketFactory(valkeyCertificateAuthority.get());
JedisClientConfig clientConfig =
DefaultJedisClientConfig.builder()
.ssl(true)
@@ -92,29 +95,26 @@ public final class CacheModule {
@Provides
@Singleton
public static DomainCache provideDomainCache(
Optional<SimplifiedJedisClient> domainJedisClient, Clock clock) {
if (domainJedisClient.isEmpty()) {
Optional<SimplifiedJedisClient> jedisClient, Clock clock, CacheMetrics cacheMetrics) {
if (jedisClient.isEmpty()) {
return domainName ->
ForeignKeyUtils.loadResourceByCache(Domain.class, domainName, clock.now());
}
return new MultilayerDomainCache(domainJedisClient.get(), clock);
return new MultilayerDomainCache(jedisClient.get(), clock, cacheMetrics);
}
@Provides
@Singleton
public static HostCache provideHostCache(Optional<SimplifiedJedisClient> hostJedisClient) {
if (hostJedisClient.isEmpty()) {
public static HostCache provideHostCache(
Optional<SimplifiedJedisClient> jedisClient, CacheMetrics cacheMetrics) {
if (jedisClient.isEmpty()) {
return repoId ->
Optional.ofNullable(EppResource.loadByCache(VKey.create(Host.class, repoId)));
}
return new MultilayerHostCache(hostJedisClient.get());
return new MultilayerHostCache(jedisClient.get(), cacheMetrics);
}
@Provides
@Singleton
@Config("valkeySslSocketFactory")
static SSLSocketFactory provideValkeySslSocketFactory(
@Config("valkeyCertificateAuthority") String valkeyCertificateAuthority) {
private static SSLSocketFactory createValkeySslSocketFactory(String valkeyCertificateAuthority) {
try {
ImmutableList<X509Certificate> trustedCerts =
CertificateFactory.getInstance("X.509")

View File

@@ -32,8 +32,9 @@ public class MultilayerDomainCache extends MultilayerEppResourceCache<Domain>
private final Clock clock;
public MultilayerDomainCache(SimplifiedJedisClient jedisClient, Clock clock) {
super(jedisClient);
public MultilayerDomainCache(
SimplifiedJedisClient jedisClient, Clock clock, CacheMetrics cacheMetrics) {
super(jedisClient, cacheMetrics);
this.clock = clock;
}

View File

@@ -36,9 +36,12 @@ public abstract class MultilayerEppResourceCache<V extends EppResource> {
.build();
private final SimplifiedJedisClient jedisClient;
private final CacheMetrics cacheMetrics;
protected MultilayerEppResourceCache(SimplifiedJedisClient jedisClient) {
protected MultilayerEppResourceCache(
SimplifiedJedisClient jedisClient, CacheMetrics cacheMetrics) {
this.jedisClient = jedisClient;
this.cacheMetrics = cacheMetrics;
}
protected abstract Optional<V> loadFromDatabase(String key);
@@ -51,6 +54,7 @@ public abstract class MultilayerEppResourceCache<V extends EppResource> {
// hopefully the resource is in the local cache
Optional<V> possibleValue = Optional.ofNullable(localCache.getIfPresent(key));
if (possibleValue.isPresent()) {
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.LOCAL);
return possibleValue;
}
@@ -58,19 +62,22 @@ public abstract class MultilayerEppResourceCache<V extends EppResource> {
possibleValue = jedisClient.get(clazz, key);
if (possibleValue.isPresent()) {
localCache.put(key, possibleValue.get());
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.REMOTE);
return possibleValue;
}
// lastly, try the DB
return loadFromDatabase(key)
.map(
v -> {
// Optional has no direct "peek" functionality to fill the caches
if (shouldPersistToRemoteCache(v)) {
jedisClient.set(new SimplifiedJedisClient.JedisResource<>(key, v));
}
localCache.put(key, v);
return v;
});
possibleValue = loadFromDatabase(key);
if (possibleValue.isEmpty()) {
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.MISS_NONEXISTENT);
return possibleValue;
}
V value = possibleValue.get();
if (shouldPersistToRemoteCache(value)) {
jedisClient.set(new SimplifiedJedisClient.JedisResource<>(key, value));
}
localCache.put(key, value);
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.MISS);
return possibleValue;
}
}

View File

@@ -27,8 +27,8 @@ import java.util.Optional;
*/
public class MultilayerHostCache extends MultilayerEppResourceCache<Host> implements HostCache {
public MultilayerHostCache(SimplifiedJedisClient jedisClient) {
super(jedisClient);
public MultilayerHostCache(SimplifiedJedisClient jedisClient, CacheMetrics cacheMetrics) {
super(jedisClient, cacheMetrics);
}
@Override

View File

@@ -155,7 +155,7 @@ public class DelegatedCredentials extends GoogleCredentials {
@Override
public AccessToken refreshAccessToken() throws IOException {
JsonFactory jsonFactory = JSON_FACTORY;
long currentTime = clock.now().toEpochMilli();
long currentTime = clock.nowMillis();
String assertion = createAssertion(jsonFactory, currentTime);
GenericData tokenRequest = new GenericData();

View File

@@ -50,6 +50,7 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.net.URI;
import java.net.URL;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.util.Map.Entry;
@@ -57,7 +58,6 @@ import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.joda.time.DateTimeConstants;
/**
* Central clearing-house for all configuration.
@@ -271,7 +271,7 @@ public final class RegistryConfig {
@Provides
@Config("brdaDayOfWeek")
public static int provideBrdaDayOfWeek() {
return DateTimeConstants.TUESDAY;
return DayOfWeek.TUESDAY.getValue();
}
/**
@@ -1637,7 +1637,6 @@ public final class RegistryConfig {
return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix;
}
/** A discount for all sunrise domain creates, between 0.0 (no discount) and 1.0 (free). */
public static double getSunriseDomainCreateDiscount() {
return CONFIG_SETTINGS.get().registryPolicy.sunriseDomainCreateDiscount;

View File

@@ -71,7 +71,6 @@
<max-backoff>180s</max-backoff>
</queue>
<!-- Queue for tasks that communicate with TMCH MarksDB webserver. -->
<queue>
<name>marksdb</name>

View File

@@ -36,13 +36,13 @@ import static google.registry.persistence.PersistenceModule.TransactionIsolation
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static org.json.simple.JSONValue.toJSONString;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.InternetDomainName;
import com.google.common.net.MediaType;
import com.google.gson.Gson;
import dagger.Module;
import dagger.Provides;
import google.registry.flows.domain.DomainFlowUtils.BadCommandForRegistryPhaseException;
@@ -83,6 +83,7 @@ public class CheckApiAction implements Runnable {
@Inject Response response;
@Inject CheckApiMetric.Builder metricBuilder;
@Inject CheckApiMetrics checkApiMetrics;
@Inject Gson gson;
@Inject
CheckApiAction() {}
@@ -94,7 +95,7 @@ public class CheckApiAction implements Runnable {
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
response.setContentType(MediaType.JSON_UTF_8);
response.setPayload(toJSONString(doCheck()));
response.setPayload(gson.toJson(doCheck()));
} finally {
CheckApiMetric metric = metricBuilder.build();
checkApiMetrics.incrementCheckApiRequest(metric);

View File

@@ -24,6 +24,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import google.registry.flows.FlowModule.EppExceptionInProviderException;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppinput.EppInput;
@@ -34,7 +35,6 @@ import google.registry.model.eppoutput.Result.Code;
import google.registry.monitoring.whitebox.EppMetric;
import jakarta.inject.Inject;
import java.util.Optional;
import org.json.simple.JSONValue;
/**
* An implementation of the EPP command/response protocol.
@@ -50,6 +50,8 @@ public final class EppController {
@Inject EppMetric.Builder eppMetricBuilder;
@Inject EppMetrics eppMetrics;
@Inject ServerTridProvider serverTridProvider;
@Inject Gson gson;
@Inject EppController() {}
/** Reads EPP XML, executes the matching flow, and returns an {@link EppOutput}. */
@@ -72,7 +74,7 @@ public final class EppController {
e.getMessage(),
lazy(
() ->
JSONValue.toJSONString(
gson.toJson(
ImmutableMap.<String, Object>of(
"clientId",
nullToEmpty(sessionMetadata.getRegistrarId()),

View File

@@ -49,4 +49,3 @@ public class EppTlsAction implements Runnable {
inputXmlBytes);
}
}

View File

@@ -19,16 +19,6 @@ import dagger.Provides;
import dagger.Subcomponent;
import google.registry.batch.BatchModule;
import google.registry.dns.DnsModule;
import google.registry.flows.contact.ContactCheckFlow;
import google.registry.flows.contact.ContactCreateFlow;
import google.registry.flows.contact.ContactDeleteFlow;
import google.registry.flows.contact.ContactInfoFlow;
import google.registry.flows.contact.ContactTransferApproveFlow;
import google.registry.flows.contact.ContactTransferCancelFlow;
import google.registry.flows.contact.ContactTransferQueryFlow;
import google.registry.flows.contact.ContactTransferRejectFlow;
import google.registry.flows.contact.ContactTransferRequestFlow;
import google.registry.flows.contact.ContactUpdateFlow;
import google.registry.flows.custom.CustomLogicModule;
import google.registry.flows.domain.DomainCheckFlow;
import google.registry.flows.domain.DomainClaimsCheckFlow;
@@ -54,6 +44,8 @@ import google.registry.flows.session.HelloFlow;
import google.registry.flows.session.LoginFlow;
import google.registry.flows.session.LogoutFlow;
import google.registry.model.eppcommon.Trid;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/** Dagger component for flow classes. */
@FlowScope
@@ -69,16 +61,6 @@ public interface FlowComponent {
FlowRunner flowRunner();
// Flows must be added here and in FlowComponentModule below.
ContactCheckFlow contactCheckFlow();
ContactCreateFlow contactCreateFlow();
ContactDeleteFlow contactDeleteFlow();
ContactInfoFlow contactInfoFlow();
ContactTransferApproveFlow contactTransferApproveFlow();
ContactTransferCancelFlow contactTransferCancelFlow();
ContactTransferQueryFlow contactTransferQueryFlow();
ContactTransferRejectFlow contactTransferRejectFlow();
ContactTransferRequestFlow contactTransferRequestFlow();
ContactUpdateFlow contactUpdateFlow();
DomainCheckFlow domainCheckFlow();
DomainClaimsCheckFlow domainClaimsCheckFlow();
DomainCreateFlow domainCreateFlow();
@@ -118,40 +100,16 @@ public interface FlowComponent {
// TODO(b/29874464): fix this in a cleaner way.
@Provides
static Flow provideFlow(FlowComponent flows, Class<? extends Flow> clazz) {
return clazz.equals(ContactCheckFlow.class) ? flows.contactCheckFlow()
: clazz.equals(ContactCreateFlow.class) ? flows.contactCreateFlow()
: clazz.equals(ContactDeleteFlow.class) ? flows.contactDeleteFlow()
: clazz.equals(ContactInfoFlow.class) ? flows.contactInfoFlow()
: clazz.equals(ContactTransferApproveFlow.class) ? flows.contactTransferApproveFlow()
: clazz.equals(ContactTransferCancelFlow.class) ? flows.contactTransferCancelFlow()
: clazz.equals(ContactTransferQueryFlow.class) ? flows.contactTransferQueryFlow()
: clazz.equals(ContactTransferRejectFlow.class) ? flows.contactTransferRejectFlow()
: clazz.equals(ContactTransferRequestFlow.class) ? flows.contactTransferRequestFlow()
: clazz.equals(ContactUpdateFlow.class) ? flows.contactUpdateFlow()
: clazz.equals(DomainCheckFlow.class) ? flows.domainCheckFlow()
: clazz.equals(DomainClaimsCheckFlow.class) ? flows.domainClaimsCheckFlow()
: clazz.equals(DomainCreateFlow.class) ? flows.domainCreateFlow()
: clazz.equals(DomainDeleteFlow.class) ? flows.domainDeleteFlow()
: clazz.equals(DomainInfoFlow.class) ? flows.domainInfoFlow()
: clazz.equals(DomainRenewFlow.class) ? flows.domainRenewFlow()
: clazz.equals(DomainRestoreRequestFlow.class) ? flows.domainRestoreRequestFlow()
: clazz.equals(DomainTransferApproveFlow.class) ? flows.domainTransferApproveFlow()
: clazz.equals(DomainTransferCancelFlow.class) ? flows.domainTransferCancelFlow()
: clazz.equals(DomainTransferQueryFlow.class) ? flows.domainTransferQueryFlow()
: clazz.equals(DomainTransferRejectFlow.class) ? flows.domainTransferRejectFlow()
: clazz.equals(DomainTransferRequestFlow.class) ? flows.domainTransferRequestFlow()
: clazz.equals(DomainUpdateFlow.class) ? flows.domainUpdateFlow()
: clazz.equals(HostCheckFlow.class) ? flows.hostCheckFlow()
: clazz.equals(HostCreateFlow.class) ? flows.hostCreateFlow()
: clazz.equals(HostDeleteFlow.class) ? flows.hostDeleteFlow()
: clazz.equals(HostInfoFlow.class) ? flows.hostInfoFlow()
: clazz.equals(HostUpdateFlow.class) ? flows.hostUpdateFlow()
: clazz.equals(PollAckFlow.class) ? flows.pollAckFlow()
: clazz.equals(PollRequestFlow.class) ? flows.pollRequestFlow()
: clazz.equals(HelloFlow.class) ? flows.helloFlow()
: clazz.equals(LoginFlow.class) ? flows.loginFlow()
: clazz.equals(LogoutFlow.class) ? flows.logoutFlow()
: null;
String simpleName = clazz.getSimpleName();
// The method name is the same as the class name but with the first character being lowercase
String methodName = Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
try {
Method method = FlowComponent.class.getMethod(methodName);
method.setAccessible(true);
return (Flow) method.invoke(flows);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}

View File

@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import google.registry.flows.FlowModule.InputXml;
import google.registry.flows.FlowModule.RegistrarId;
import google.registry.flows.annotations.ReportingSpec;
@@ -30,7 +31,6 @@ import google.registry.model.eppcommon.Trid;
import google.registry.model.eppinput.EppInput;
import jakarta.inject.Inject;
import java.util.Optional;
import org.json.simple.JSONValue;
/** Reporter used by {@link FlowRunner} to record flow execution data for reporting. */
public class FlowReporter {
@@ -49,6 +49,8 @@ public class FlowReporter {
@Inject @InputXml byte[] inputXmlBytes;
@Inject EppInput eppInput;
@Inject Class<? extends Flow> flowClass;
@Inject Gson gson;
@Inject FlowReporter() {}
/** Records information about the current flow execution in the request logs. */
@@ -61,7 +63,7 @@ public class FlowReporter {
logger.atInfo().log(
"%s: %s",
METADATA_LOG_SIGNATURE,
JSONValue.toJSONString(
gson.toJson(
new ImmutableMap.Builder<String, Object>()
.put("serverTrid", trid.getServerTransactionId())
.put("clientId", registrarId)

View File

@@ -71,6 +71,4 @@ public class StatelessRequestSessionMetadata extends SessionMetadata {
throw new UnsupportedOperationException();
}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to check whether a contact can be provisioned.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_CHECK)
public final class ContactCheckFlow extends ContactsProhibitedFlow {
@Inject ContactCheckFlow() {}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow meant to create a new contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_CREATE)
public final class ContactCreateFlow extends ContactsProhibitedFlow {
@Inject ContactCreateFlow() {}
}

View File

@@ -1,33 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to delete a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_DELETE)
public final class ContactDeleteFlow extends ContactsProhibitedFlow {
@Inject
ContactDeleteFlow() {}
}

View File

@@ -1,33 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to return information about a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_INFO)
public final class ContactInfoFlow extends ContactsProhibitedFlow {
@Inject
ContactInfoFlow() {}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to approve a pending transfer on a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_APPROVE)
public final class ContactTransferApproveFlow extends ContactsProhibitedFlow {
@Inject ContactTransferApproveFlow() {}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to cancel a pending transfer on a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_CANCEL)
public final class ContactTransferCancelFlow extends ContactsProhibitedFlow {
@Inject ContactTransferCancelFlow() {}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to query a pending transfer on a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_QUERY)
public final class ContactTransferQueryFlow extends ContactsProhibitedFlow {
@Inject ContactTransferQueryFlow() {}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to reject a pending transfer on a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REJECT)
public final class ContactTransferRejectFlow extends ContactsProhibitedFlow {
@Inject ContactTransferRejectFlow() {}
}

View File

@@ -1,33 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow that is meant to request a transfer on a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REQUEST)
public final class ContactTransferRequestFlow extends ContactsProhibitedFlow {
@Inject
ContactTransferRequestFlow() {}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import jakarta.inject.Inject;
/**
* An EPP flow meant to update a contact.
*
* @error {@link ContactsProhibitedException}
*/
@Deprecated
@ReportingSpec(ActivityReportField.CONTACT_UPDATE)
public final class ContactUpdateFlow extends ContactsProhibitedFlow {
@Inject ContactUpdateFlow() {}
}

View File

@@ -1,28 +0,0 @@
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows.contact;
import google.registry.flows.EppException;
import google.registry.flows.Flow;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.eppoutput.EppResponse;
/** Nomulus follows the Minimum Dataset Requirements, meaning it stores no contact information. */
public abstract class ContactsProhibitedFlow implements Flow {
@Override
public EppResponse run() throws EppException {
throw new ContactsProhibitedException();
}
}

View File

@@ -57,6 +57,9 @@ public final class DomainFlowTmchUtils {
public SignedMark verifySignedMarks(
ImmutableList<AbstractSignedMark> signedMarks, String domainLabel, Instant now)
throws EppException {
if (signedMarks.isEmpty()) {
throw new SignedMarksListEmptyException();
}
if (signedMarks.size() > 1) {
throw new TooManySignedMarksException();
}
@@ -77,21 +80,21 @@ public final class DomainFlowTmchUtils {
public SignedMark verifyEncodedSignedMark(EncodedSignedMark encodedSignedMark, Instant now)
throws EppException {
if (!encodedSignedMark.getEncoding().equals("base64")) {
if (!"base64".equals(encodedSignedMark.getEncoding())) {
throw new Base64RequiredForEncodedSignedMarksException();
}
byte[] signedMarkData;
try {
signedMarkData = encodedSignedMark.getBytes();
} catch (IllegalStateException e) {
throw new SignedMarkEncodingErrorException();
throw new SignedMarkEncodingErrorException(e);
}
SignedMark signedMark;
try {
signedMark = unmarshalEpp(SignedMark.class, signedMarkData);
} catch (EppException e) {
throw new SignedMarkParsingErrorException();
throw new SignedMarkParsingErrorException(e);
}
if (SignedMarkRevocationList.get().isSmdRevoked(signedMark.getId(), now)) {
@@ -101,22 +104,22 @@ public final class DomainFlowTmchUtils {
try {
tmchXmlSignature.verify(signedMarkData);
} catch (CertificateExpiredException e) {
throw new SignedMarkCertificateExpiredException();
throw new SignedMarkCertificateExpiredException(e);
} catch (CertificateNotYetValidException e) {
throw new SignedMarkCertificateNotYetValidException();
throw new SignedMarkCertificateNotYetValidException(e);
} catch (CertificateRevokedException e) {
throw new SignedMarkCertificateRevokedException();
throw new SignedMarkCertificateRevokedException(e);
} catch (CertificateSignatureException e) {
throw new SignedMarkCertificateSignatureException();
throw new SignedMarkCertificateSignatureException(e);
} catch (SignatureException | XMLSignatureException e) {
throw new SignedMarkSignatureException();
throw new SignedMarkSignatureException(e);
} catch (GeneralSecurityException e) {
throw new SignedMarkCertificateInvalidException();
throw new SignedMarkCertificateInvalidException(e);
} catch (IOException
| MarshalException
| SAXException
| ParserConfigurationException e) {
throw new SignedMarkParsingErrorException();
throw new SignedMarkParsingErrorException(e);
}
if (now.isBefore(signedMark.getCreationTime())) {
@@ -181,6 +184,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkCertificateRevokedException() {
super("Signed mark certificate was revoked");
}
public SignedMarkCertificateRevokedException(Throwable cause) {
this();
initCause(cause);
}
}
/** Certificate used in signed mark signature has expired. */
@@ -189,6 +197,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkCertificateNotYetValidException() {
super("Signed mark certificate not yet valid");
}
public SignedMarkCertificateNotYetValidException(Throwable cause) {
this();
initCause(cause);
}
}
/** Certificate used in signed mark signature has expired. */
@@ -196,6 +209,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkCertificateExpiredException() {
super("Signed mark certificate has expired");
}
public SignedMarkCertificateExpiredException(Throwable cause) {
this();
initCause(cause);
}
}
/** Certificate parsing error, or possibly a bad provider or algorithm. */
@@ -203,6 +221,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkCertificateInvalidException() {
super("Signed mark certificate is invalid");
}
public SignedMarkCertificateInvalidException(Throwable cause) {
this();
initCause(cause);
}
}
/** Invalid signature on a signed mark. */
@@ -210,6 +233,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkCertificateSignatureException() {
super("Signed mark certificate not signed by ICANN");
}
public SignedMarkCertificateSignatureException(Throwable cause) {
this();
initCause(cause);
}
}
/** Invalid signature on a signed mark. */
@@ -217,6 +245,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkSignatureException() {
super("Signed mark signature is invalid");
}
public SignedMarkSignatureException(Throwable cause) {
this();
initCause(cause);
}
}
/** Signed marks must be encoded. */
@@ -226,6 +259,13 @@ public final class DomainFlowTmchUtils {
}
}
/** Signed marks list cannot be empty. */
static class SignedMarksListEmptyException extends RequiredParameterMissingException {
public SignedMarksListEmptyException() {
super("Signed marks list cannot be empty");
}
}
/** Only one signed mark is allowed per application. */
static class TooManySignedMarksException extends ParameterValuePolicyErrorException {
public TooManySignedMarksException() {
@@ -245,6 +285,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkParsingErrorException() {
super("Error while parsing encoded signed mark data");
}
public SignedMarkParsingErrorException(Throwable cause) {
this();
initCause(cause);
}
}
/** Signed mark data is improperly encoded. */
@@ -252,6 +297,11 @@ public final class DomainFlowTmchUtils {
public SignedMarkEncodingErrorException() {
super("Signed mark data is improperly encoded");
}
public SignedMarkEncodingErrorException(Throwable cause) {
this();
initCause(cause);
}
}
}

View File

@@ -23,6 +23,7 @@ import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static com.google.common.collect.Sets.union;
import static google.registry.bsa.persistence.BsaLabelUtils.isLabelBlocked;
import static google.registry.model.common.FeatureFlag.FeatureName.FORBID_INSECURE_ALGORITHMS_RFC_9904;
import static google.registry.model.domain.Domain.MAX_REGISTRATION_YEARS;
import static google.registry.model.domain.token.AllocationToken.TokenType.REGISTER_BSA;
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
@@ -43,8 +44,8 @@ import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static google.registry.util.DateTimeUtils.minusDays;
import static google.registry.util.DateTimeUtils.plusYears;
import static google.registry.util.DomainNameUtils.ACE_PREFIX;
import static java.time.ZoneOffset.UTC;
import static java.util.stream.Collectors.joining;
import com.google.common.base.CharMatcher;
@@ -73,6 +74,7 @@ import google.registry.model.EppResource;
import google.registry.model.billing.BillingBase.Flag;
import google.registry.model.billing.BillingBase.Reason;
import google.registry.model.billing.BillingRecurrence;
import google.registry.model.common.FeatureFlag;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainCommand.Create;
import google.registry.model.domain.DomainCommand.CreateOrUpdate;
@@ -154,7 +156,7 @@ public class DomainFlowUtils {
/** Warning message for allocation of collision domains in sunrise. */
public static final String COLLISION_MESSAGE =
"Domain on the name collision list was allocated. But by policy, the domain will not be "
+ "delegated. Please visit https://www.icann.org/namecollision for more information on "
+ "delegated. Please visit https://www.icann.org/namecollision for more information on "
+ "name collision.";
/** Strict validator for ascii lowercase letters, digits, and "-", allowing "." as a separator */
@@ -341,7 +343,7 @@ public class DomainFlowUtils {
}
ImmutableList<DomainDsData> invalidAlgorithms =
dsData.stream()
.filter(ds -> !validateAlgorithm(ds.getAlgorithm()))
.filter(ds -> algorithmIsInvalid(ds.getAlgorithm()))
.collect(toImmutableList());
if (!invalidAlgorithms.isEmpty()) {
throw new InvalidDsRecordException(
@@ -349,9 +351,16 @@ public class DomainFlowUtils {
"Domain contains DS record(s) with an invalid algorithm wire value: %s",
invalidAlgorithms));
}
boolean forbidInsecureTypes = FeatureFlag.isActiveNow(FORBID_INSECURE_ALGORITHMS_RFC_9904);
ImmutableList<DomainDsData> invalidDigestTypes =
dsData.stream()
.filter(ds -> DigestType.fromWireValue(ds.getDigestType()).isEmpty())
.filter(
ds -> {
Optional<DigestType> digestType = DigestType.fromWireValue(ds.getDigestType());
return digestType
.map(type -> forbidInsecureTypes && !type.isAllowedInRfc9904())
.orElse(true);
})
.collect(toImmutableList());
if (!invalidDigestTypes.isEmpty()) {
throw new InvalidDsRecordException(
@@ -376,14 +385,14 @@ public class DomainFlowUtils {
}
}
public static boolean validateAlgorithm(int alg) {
public static boolean algorithmIsInvalid(int alg) {
if (alg > 255 || alg < 0) {
return false;
return true;
}
// Algorithms that are reserved or unassigned will just return a string representation of their
// integer wire value.
String algorithm = Algorithm.string(alg);
return !algorithm.equals(Integer.toString(alg));
return algorithm.equals(Integer.toString(alg));
}
/** We only allow specifying years in a period. */
@@ -581,13 +590,12 @@ public class DomainFlowUtils {
InternetDomainName domainName,
Optional<Domain> domain,
@Nullable CurrencyUnit topLevelCurrency,
Instant currentDate,
Instant now,
DomainPricingLogic pricingLogic,
Optional<AllocationToken> allocationToken,
boolean isAvailable,
@Nullable BillingRecurrence billingRecurrence)
throws EppException {
Instant now = currentDate;
// Use the custom effective date specified in the fee check request, if there is one.
if (feeRequest.getEffectiveDate().isPresent()) {
now = feeRequest.getEffectiveDate().get();
@@ -816,7 +824,7 @@ public class DomainFlowUtils {
return fee.getType();
}
ImmutableList<FeeType> types = fee.parseDescriptionForTypes();
if (types.size() == 0) {
if (types.isEmpty()) {
throw new FeeDescriptionParseException(fee.getDescription());
} else if (types.size() > 1) {
throw new FeeDescriptionMultipleMatchesException(fee.getDescription(), types);
@@ -848,7 +856,7 @@ public class DomainFlowUtils {
*/
public static void validateRegistrationPeriod(Instant now, Instant newExpirationTime)
throws EppException {
if (now.atZone(UTC).plusYears(MAX_REGISTRATION_YEARS).toInstant().isBefore(newExpirationTime)) {
if (plusYears(now, MAX_REGISTRATION_YEARS).isBefore(newExpirationTime)) {
throw new ExceedsMaxRegistrationYearsException();
}
}
@@ -907,7 +915,7 @@ public class DomainFlowUtils {
return ImmutableSet.copyOf(union(difference(oldDsData, toRemove), toAdd));
}
/** If a domain "clientUpdateProhibited" set, updates must clear it or fail. */
/** If a domain has "clientUpdateProhibited" set, updates must clear it or fail. */
static void verifyClientUpdateNotProhibited(Update command, Domain existingResource)
throws ResourceHasClientUpdateProhibitedException {
if (existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)
@@ -996,7 +1004,13 @@ public class DomainFlowUtils {
}
}
/** Check that the claims period hasn't ended. */
/**
* Check that the claims period hasn't ended.
*
* @param tld the {@link Tld} to check
* @param now the current {@link Instant}
* @throws ClaimsPeriodEndedException if the claims period has ended
*/
static void verifyClaimsPeriodNotEnded(Tld tld, Instant now) throws ClaimsPeriodEndedException {
if (!now.isBefore(tld.getClaimsPeriodEnd())) {
throw new ClaimsPeriodEndedException(tld.getTldStr());
@@ -1008,6 +1022,9 @@ public class DomainFlowUtils {
*
* <p>{@link BigDecimal} has a concept of significant figures, so zero is not always zero. E.g.
* zero in USD is 0.00, whereas zero in Yen is 0, and zero in Dinars is 0.000 (!).
*
* @param currencyUnit the {@link CurrencyUnit}
* @return zero in the given currency
*/
static BigDecimal zeroInCurrency(CurrencyUnit currencyUnit) {
return Money.of(currencyUnit, BigDecimal.ZERO).getAmount();
@@ -1016,6 +1033,12 @@ public class DomainFlowUtils {
/**
* Check that if there's a claims notice it's on the claims list, and that if there's not one it's
* not on the claims list.
*
* @param domainName the {@link InternetDomainName} to check
* @param claimsList the current {@link ClaimsList}
* @param hasSignedMarks whether signed marks are present
* @param hasClaimsNotice whether a claims notice is present
* @throws EppException if the claims notice status is incorrect
*/
static void verifyClaimsNoticeIfAndOnlyIfNeeded(
InternetDomainName domainName,
@@ -1032,7 +1055,12 @@ public class DomainFlowUtils {
}
}
/** Check that there are no code marks, which is a type of mark we don't support. */
/**
* Check that there are no code marks, which is a type of mark we don't support.
*
* @param launchCreate the {@link LaunchCreateExtension}
* @throws UnsupportedMarkTypeException if code marks are present
*/
static void verifyNoCodeMarks(LaunchCreateExtension launchCreate)
throws UnsupportedMarkTypeException {
if (launchCreate.hasCodeMarks()) {
@@ -1040,7 +1068,13 @@ public class DomainFlowUtils {
}
}
/** Create a response extension listing the fees on a domain create. */
/**
* Create a response extension listing the fees on a domain create.
*
* @param feeCreate the {@link FeeTransformCommandExtension}
* @param feesAndCredits the {@link FeesAndCredits}
* @return the {@link FeeTransformResponseExtension}
*/
static FeeTransformResponseExtension createFeeCreateResponse(
FeeTransformCommandExtension feeCreate, FeesAndCredits feesAndCredits) {
return feeCreate
@@ -1058,10 +1092,21 @@ public class DomainFlowUtils {
* their flow. For example, if a grace period delete occurs, we must add -1 counters for the
* associated NET_ADDS_#_YRS field, if it exists.
*
* <p>The steps are as follows: 1. Find all HistoryEntries under the domain modified in the past,
* up to the maxSearchPeriod. 2. Only keep HistoryEntries with a DomainTransactionRecord that a)
* hasn't been reported yet and b) matches the predicate 3. Return the transactionRecords under
* the most recent HistoryEntry that fits the above criteria, with negated reportAmounts.
* <p>The steps are as follows:
*
* <ol>
* <li>Find all HistoryEntries under the domain modified in the past, up to the maxSearchPeriod.
* <li>Only keep HistoryEntries with a DomainTransactionRecord that a) hasn't been reported yet
* and b) matches the predicate
* <li>Return the transactionRecords under the most recent HistoryEntry that fits the above
* criteria, with negated reportAmounts.
* </ol>
*
* @param domain the {@link Domain} to create records for
* @param now the current {@link Instant}
* @param maxSearchPeriod the {@link Duration} to search back
* @param cancelableFields the set of {@link TransactionReportField}s that can be canceled
* @return the set of canceling {@link DomainTransactionRecord}s
*/
public static ImmutableSet<DomainTransactionRecord> createCancelingRecords(
Domain domain,
@@ -1225,13 +1270,6 @@ public class DomainFlowUtils {
}
}
/** Having a registrant is prohibited by registry policy. */
public static class RegistrantProhibitedException extends ParameterValuePolicyErrorException {
public RegistrantProhibitedException() {
super("Having a registrant is prohibited by registry policy");
}
}
/** Too many nameservers set on this domain. */
static class TooManyNameserversException extends ParameterValuePolicyErrorException {
public TooManyNameserversException(String message) {
@@ -1384,6 +1422,13 @@ public class DomainFlowUtils {
}
}
/** Having a registrant is prohibited by registry policy. */
public static class RegistrantProhibitedException extends ParameterValuePolicyErrorException {
public RegistrantProhibitedException() {
super("Having a registrant is prohibited by registry policy");
}
}
/** The fee description passed in the transform command cannot be parsed. */
public static class FeeDescriptionParseException extends ParameterValuePolicyErrorException {
public FeeDescriptionParseException(String description) {

View File

@@ -34,8 +34,8 @@ import static google.registry.flows.domain.token.AllocationTokenFlowUtils.maybeA
import static google.registry.flows.domain.token.AllocationTokenFlowUtils.verifyBulkTokenAllowedOnDomain;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_RENEW;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.plusYears;
import static google.registry.util.DateTimeUtils.toLocalDate;
import static java.time.ZoneOffset.UTC;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -192,11 +192,7 @@ public final class DomainRenewFlow implements MutatingFlow {
existingDomain = maybeApplyBulkPricingRemovalToken(existingDomain, allocationToken);
Instant newExpirationTime =
existingDomain
.getRegistrationExpirationTime()
.atZone(UTC)
.plusYears(years)
.toInstant(); // Uncapped
plusYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped
validateRegistrationPeriod(now, newExpirationTime);
Optional<FeeRenewCommandExtension> feeRenew =
eppInput.getSingleExtension(FeeRenewCommandExtension.class);

View File

@@ -14,7 +14,6 @@
package google.registry.flows.domain;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet;
import static com.google.common.collect.Sets.symmetricDifference;
import static com.google.common.collect.Sets.union;
@@ -58,17 +57,17 @@ import google.registry.flows.custom.DomainUpdateFlowCustomLogic.BeforeSaveParame
import google.registry.flows.custom.EntityChanges;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverAllowListException;
import google.registry.flows.domain.DomainFlowUtils.RegistrantProhibitedException;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingBase.Reason;
import google.registry.model.billing.BillingEvent;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainCommand.Update;
import google.registry.model.domain.DomainCommand.Update.AddRemove;
import google.registry.model.domain.DomainCommand.Update.Change;
import google.registry.model.domain.DomainCommand.Update.DomainAddRemove;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.fee.FeeUpdateCommandExtension;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.secdns.DomainDsData;
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Add;
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
@@ -118,6 +117,7 @@ import java.util.Optional;
* @error {@link NameserversNotSpecifiedForTldWithNameserverAllowListException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link RegistrantProhibitedException}
* @error {@link ContactsProhibitedException}
* @error {@link DomainFlowUtils.SecDnsAllUsageException}
* @error {@link DomainFlowUtils.TooManyDsRecordsException}
* @error {@link DomainFlowUtils.TooManyNameserversException}
@@ -214,8 +214,8 @@ public final class DomainUpdateFlow implements MutatingFlow {
private void verifyUpdateAllowed(Update command, Domain existingDomain, Instant now)
throws EppException {
verifyOptionalAuthInfo(authInfo, existingDomain);
AddRemove add = command.getInnerAdd();
AddRemove remove = command.getInnerRemove();
DomainAddRemove add = command.getInnerAdd();
DomainAddRemove remove = command.getInnerRemove();
String tldStr = existingDomain.getTld();
if (!isSuperuser) {
verifyNoDisallowedStatuses(existingDomain, UPDATE_DISALLOWED_STATUSES);
@@ -234,8 +234,8 @@ public final class DomainUpdateFlow implements MutatingFlow {
}
private Domain performUpdate(Update command, Domain domain, Instant now) throws EppException {
AddRemove add = command.getInnerAdd();
AddRemove remove = command.getInnerRemove();
DomainAddRemove add = command.getInnerAdd();
DomainAddRemove remove = command.getInnerRemove();
Optional<SecDnsUpdateExtension> secDnsUpdate =
eppInput.getSingleExtension(SecDnsUpdateExtension.class);
verifyAddsAndRemoves(domain.getNameservers(), add.getNameservers(), remove.getNameservers());
@@ -251,28 +251,29 @@ public final class DomainUpdateFlow implements MutatingFlow {
Domain.Builder domainBuilder =
domain
.asBuilder()
// Handle the secDNS extension. As dsData in secDnsUpdate is read from EPP input and
// does not have domainRepoId set, we create a copy of the existing dsData without
// domainRepoId for comparison.
// Handle the secDNS extension.
.setDsData(
secDnsUpdate.isPresent()
? updateDsData(
domain.getDsData().stream()
.map(DomainDsData::cloneWithoutDomainRepoId)
.collect(toImmutableSet()),
secDnsUpdate.get())
? updateDsData(domain.getDsData(), secDnsUpdate.get())
: domain.getDsData())
.setLastEppUpdateTime(now)
.setLastEppUpdateRegistrarId(registrarId)
.addStatusValues(add.getStatusValues())
.removeStatusValues(remove.getStatusValues())
.setAuthInfo(Optional.ofNullable(change.getAuthInfo()).orElse(domain.getAuthInfo()));
.setLastEppUpdateRegistrarId(registrarId);
if (!add.getStatusValues().isEmpty()) {
domainBuilder.addStatusValues(add.getStatusValues());
}
if (!remove.getStatusValues().isEmpty()) {
domainBuilder.removeStatusValues(remove.getStatusValues());
}
domainBuilder.setAuthInfo(
Optional.ofNullable(change.getAuthInfo()).orElse(domain.getAuthInfo()));
if (!add.getNameservers().isEmpty()) {
domainBuilder.addNameservers(add.getNameservers().stream().collect(toImmutableSet()));
domainBuilder.addNameservers(add.getNameservers());
}
if (!remove.getNameservers().isEmpty()) {
domainBuilder.removeNameservers(remove.getNameservers().stream().collect(toImmutableSet()));
domainBuilder.removeNameservers(remove.getNameservers());
}
Optional<DomainUpdateSuperuserExtension> superuserExt =

View File

@@ -36,7 +36,6 @@ import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.google.cloud.tasks.v2.Task;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.batch.CloudTasksUtils;
import google.registry.dns.RefreshDnsOnHostRenameAction;
import google.registry.flows.EppException;
@@ -59,8 +58,8 @@ import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.Host;
import google.registry.model.host.HostCommand.Update;
import google.registry.model.host.HostCommand.Update.AddRemove;
import google.registry.model.host.HostCommand.Update.Change;
import google.registry.model.host.HostCommand.Update.HostAddRemove;
import google.registry.model.host.HostHistory;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.persistence.VKey;
@@ -122,7 +121,6 @@ public final class HostUpdateFlow implements MutatingFlow {
@Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser;
@Inject HostHistory.Builder historyBuilder;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject EppResponse.Builder responseBuilder;
@Inject CloudTasksUtils cloudTasksUtils;
@@ -148,6 +146,7 @@ public final class HostUpdateFlow implements MutatingFlow {
? tm().loadByKey(existingHost.getSuperordinateDomain()).cloneProjectedAtTime(now)
: null;
// Note that lookupSuperordinateDomain calls cloneProjectedAtTime on the domain for us.
Optional<Domain> newSuperordinateDomain =
lookupSuperordinateDomain(validateHostName(newHostName), now);
verifySuperordinateDomainNotInPendingDelete(newSuperordinateDomain.orElse(null));
@@ -157,8 +156,8 @@ public final class HostUpdateFlow implements MutatingFlow {
if (isHostRename && ForeignKeyUtils.loadKey(Host.class, newHostName, now).isPresent()) {
throw new HostAlreadyExistsException(newHostName);
}
AddRemove add = command.getInnerAdd();
AddRemove remove = command.getInnerRemove();
HostAddRemove add = command.getInnerAdd();
HostAddRemove remove = command.getInnerRemove();
verifyAddsAndRemoves(
existingHost.getStatusValues(), add.getStatusValues(), remove.getStatusValues());
verifyAddsAndRemoves(

View File

@@ -22,16 +22,6 @@ import google.registry.flows.EppException;
import google.registry.flows.EppException.SyntaxErrorException;
import google.registry.flows.EppException.UnimplementedCommandException;
import google.registry.flows.Flow;
import google.registry.flows.contact.ContactCheckFlow;
import google.registry.flows.contact.ContactCreateFlow;
import google.registry.flows.contact.ContactDeleteFlow;
import google.registry.flows.contact.ContactInfoFlow;
import google.registry.flows.contact.ContactTransferApproveFlow;
import google.registry.flows.contact.ContactTransferCancelFlow;
import google.registry.flows.contact.ContactTransferQueryFlow;
import google.registry.flows.contact.ContactTransferRejectFlow;
import google.registry.flows.contact.ContactTransferRequestFlow;
import google.registry.flows.contact.ContactUpdateFlow;
import google.registry.flows.domain.DomainCheckFlow;
import google.registry.flows.domain.DomainClaimsCheckFlow;
import google.registry.flows.domain.DomainCreateFlow;
@@ -55,7 +45,6 @@ import google.registry.flows.poll.PollRequestFlow;
import google.registry.flows.session.HelloFlow;
import google.registry.flows.session.LoginFlow;
import google.registry.flows.session.LogoutFlow;
import google.registry.model.contact.ContactCommand;
import google.registry.model.domain.DomainCommand;
import google.registry.model.domain.launch.LaunchCheckExtension;
import google.registry.model.domain.launch.LaunchCheckExtension.CheckType;
@@ -202,11 +191,6 @@ public class FlowPicker {
private static final FlowProvider RESOURCE_CRUD_FLOW_PROVIDER = new FlowProvider() {
private final Map<Class<?>, Class<? extends Flow>> resourceCrudFlows =
new ImmutableMap.Builder<Class<?>, Class<? extends Flow>>()
.put(ContactCommand.Check.class, ContactCheckFlow.class)
.put(ContactCommand.Create.class, ContactCreateFlow.class)
.put(ContactCommand.Delete.class, ContactDeleteFlow.class)
.put(ContactCommand.Info.class, ContactInfoFlow.class)
.put(ContactCommand.Update.class, ContactUpdateFlow.class)
.put(DomainCommand.Create.class, DomainCreateFlow.class)
.put(DomainCommand.Delete.class, DomainDeleteFlow.class)
.put(DomainCommand.Info.class, DomainInfoFlow.class)
@@ -230,24 +214,6 @@ public class FlowPicker {
new FlowProvider() {
private final Table<Class<?>, TransferOp, Class<? extends Flow>> transferFlows =
ImmutableTable.<Class<?>, TransferOp, Class<? extends Flow>>builder()
.put(
ContactCommand.Transfer.class,
TransferOp.APPROVE,
ContactTransferApproveFlow.class)
.put(
ContactCommand.Transfer.class,
TransferOp.CANCEL,
ContactTransferCancelFlow.class)
.put(
ContactCommand.Transfer.class, TransferOp.QUERY, ContactTransferQueryFlow.class)
.put(
ContactCommand.Transfer.class,
TransferOp.REJECT,
ContactTransferRejectFlow.class)
.put(
ContactCommand.Transfer.class,
TransferOp.REQUEST,
ContactTransferRequestFlow.class)
.put(
DomainCommand.Transfer.class,
TransferOp.APPROVE,

View File

@@ -15,7 +15,6 @@
package google.registry.flows.session;
import static com.google.common.collect.Sets.difference;
import static google.registry.model.common.FeatureFlag.FeatureName.PROHIBIT_CONTACT_OBJECTS_ON_LOGIN;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmpty;
@@ -40,7 +39,6 @@ import google.registry.flows.TlsCredentials.BadRegistrarIpAddressException;
import google.registry.flows.TlsCredentials.MissingRegistrarCertificateException;
import google.registry.flows.TransportCredentials;
import google.registry.flows.TransportCredentials.BadRegistrarPasswordException;
import google.registry.model.common.FeatureFlag;
import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppinput.EppInput;
@@ -120,9 +118,7 @@ public class LoginFlow implements MutatingFlow {
Set<String> unsupportedObjectServices =
difference(
nullToEmpty(services.getObjectServices()),
FeatureFlag.isActiveNow(PROHIBIT_CONTACT_OBJECTS_ON_LOGIN)
? ProtocolDefinition.SUPPORTED_OBJECT_SERVICES
: ProtocolDefinition.SUPPORTED_OBJECT_SERVICES_WITH_CONTACT);
ProtocolDefinition.SUPPORTED_OBJECT_SERVICES);
stopwatch.tick("LoginFlow difference unsupportedObjectServices");
if (!unsupportedObjectServices.isEmpty()) {
throw new UnimplementedObjectServiceException();

View File

@@ -56,6 +56,7 @@ public final class GmailClient {
private final InternetAddress outgoingEmailAddressWithUsername;
private final InternetAddress replyToEmailAddress;
// TODO(b/510340944): drop sender info. Sender is determined by the Gmail credential owner.
@Inject
GmailClient(
Lazy<Gmail> gmail,
@@ -77,6 +78,20 @@ public final class GmailClient {
}
}
// TODO(b/510340944): Remove this experiment method
public GmailClient(
Lazy<Gmail> gmail,
Retrier retrier,
@Config("isEmailSendingEnabled") boolean isEmailSendingEnabled,
@Config("replyToEmailAddress") InternetAddress replyToEmailAddress) {
this.gmail = gmail;
this.retrier = retrier;
this.isEmailSendingEnabled = isEmailSendingEnabled;
this.replyToEmailAddress = replyToEmailAddress;
this.outgoingEmailAddressWithUsername = null;
}
/**
* Sends {@code emailMessage} using {@link Gmail}.
*/
@@ -116,7 +131,9 @@ public final class GmailClient {
try {
MimeMessage msg =
new MimeMessage(Session.getDefaultInstance(new Properties(), /* authenticator= */ null));
msg.setFrom(this.outgoingEmailAddressWithUsername);
if (this.outgoingEmailAddressWithUsername != null) {
msg.setFrom(this.outgoingEmailAddressWithUsername);
}
msg.setReplyTo(
new InternetAddress[] {emailMessage.replyToEmailAddress().orElse(replyToEmailAddress)});
msg.addRecipients(

View File

@@ -22,6 +22,7 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.keyring.api.Keyring;
import google.registry.keyring.secretmanager.SecretManagerKeyring;
import jakarta.inject.Singleton;
import java.util.Optional;
/** Dagger module for {@link Keyring} */
@Module
@@ -55,7 +56,7 @@ public abstract class KeyringModule {
@Provides
@Config("valkeyCertificateAuthority")
public static String provideValkeyCertificateAuthority(Keyring keyring) {
return keyring.getValkeyCertificateAuthority();
public static Optional<String> provideValkeyCertificateAuthority(Keyring keyring) {
return Optional.ofNullable(keyring.getValkeyCertificateAuthority());
}
}

View File

@@ -41,7 +41,6 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
*/
public final class KeySerializer {
private KeySerializer() {}
/**

View File

@@ -21,7 +21,6 @@ import dagger.Module;
import dagger.Provides;
import google.registry.request.Parameter;
import jakarta.servlet.http.HttpServletRequest;
import org.joda.time.Minutes;
/**
* Dagger module for loadtest package.
@@ -42,15 +41,13 @@ public final class LoadTestModule {
@Provides
@Parameter("delaySeconds")
static int provideDelaySeconds(HttpServletRequest req) {
return extractOptionalIntParameter(req, "delaySeconds")
.orElse(Minutes.ONE.toStandardSeconds().getSeconds());
return extractOptionalIntParameter(req, "delaySeconds").orElse(60);
}
@Provides
@Parameter("runSeconds")
static int provideRunSeconds(HttpServletRequest req) {
return extractOptionalIntParameter(req, "runSeconds")
.orElse(Minutes.ONE.toStandardSeconds().getSeconds());
return extractOptionalIntParameter(req, "runSeconds").orElse(60);
}
@Provides

View File

@@ -106,19 +106,24 @@ public abstract class ImmutableObject implements Cloneable {
return hashCode;
}
/** Returns a clone of the given object. */
@SuppressWarnings("unchecked")
protected static <T extends ImmutableObject> T clone(T t) {
@Override
@SuppressWarnings("AmbiguousMethodReference")
public ImmutableObject clone() {
try {
T clone = (T) t.clone();
// Clear the hashCode since we often mutate clones before handing them out.
ImmutableObject clone = (ImmutableObject) super.clone();
clone.hashCode = null;
return clone;
} catch (CloneNotSupportedException e) { // Yes it is.
throw new IllegalStateException();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
/** Returns a clone of the given object. */
@SuppressWarnings({"unchecked", "AmbiguousMethodReference"})
protected static <T extends ImmutableObject> T clone(T t) {
return (T) t.clone();
}
/** Returns a clone of the given object with empty fields set to null. */
protected static <T extends ImmutableObject> T cloneEmptyToNull(T t) {
return ModelUtils.cloneEmptyToNull(t);
@@ -233,7 +238,7 @@ public abstract class ImmutableObject implements Cloneable {
}
}
/** Marker to indicate that this filed should be ignored by {@link #toDiffableFieldMap}. */
/** Marker to indicate that this field should be ignored by {@link #toDiffableFieldMap}. */
@Documented
@Retention(RUNTIME)
@Target(FIELD)

View File

@@ -90,9 +90,9 @@ public class Cursor extends UpdateAutoTimestampEntity {
RECURRING_BILLING(false),
/**
* Cursor for {@link google.registry.export.sheet.SyncRegistrarsSheetAction}. The DateTime
* stored is the last time that registrar changes were successfully synced to the sheet. If
* there were no changes since the last time the action run, the cursor is not updated.
* Cursor for {@link google.registry.export.sheet.SyncRegistrarsSheetAction}. The Instant stored
* is the last time that registrar changes were successfully synced to the sheet. If there were
* no changes since the last time the action run, the cursor is not updated.
*/
SYNC_REGISTRAR_SHEET(false),

View File

@@ -84,7 +84,10 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
INCLUDE_PENDING_DELETE_DATE_FOR_DOMAINS(FeatureStatus.INACTIVE),
/** If we're prohibiting the inclusion of the contact object URI on login. */
PROHIBIT_CONTACT_OBJECTS_ON_LOGIN(FeatureStatus.INACTIVE);
PROHIBIT_CONTACT_OBJECTS_ON_LOGIN(FeatureStatus.INACTIVE),
/** If we're prohibiting insecure algorithms as detailed by RFC 9904. */
FORBID_INSECURE_ALGORITHMS_RFC_9904(FeatureStatus.INACTIVE);
private final FeatureStatus defaultStatus;

View File

@@ -33,7 +33,7 @@ import jakarta.persistence.Embeddable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.OffsetDateTime;
import java.util.List;
/**
@@ -63,7 +63,7 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
* February 28. It is impossible to construct a {@link TimeOfYear} for February 29th.
*/
public static TimeOfYear fromInstant(Instant instant) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, UTC);
OffsetDateTime zdt = OffsetDateTime.ofInstant(instant, UTC);
int month = zdt.getMonthValue();
int day = zdt.getDayOfMonth();
if (month == 2 && day == 29) {
@@ -88,8 +88,8 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
Range<Instant> normalizedRange = range.intersection(Range.closed(START_INSTANT, END_INSTANT));
Range<Integer> yearRange =
Range.closed(
ZonedDateTime.ofInstant(normalizedRange.lowerEndpoint(), UTC).getYear(),
ZonedDateTime.ofInstant(normalizedRange.upperEndpoint(), UTC).getYear());
OffsetDateTime.ofInstant(normalizedRange.lowerEndpoint(), UTC).getYear(),
OffsetDateTime.ofInstant(normalizedRange.upperEndpoint(), UTC).getYear());
return ContiguousSet.create(yearRange, integers()).stream()
.map(this::toInstantWithYear)
.filter(normalizedRange)
@@ -112,13 +112,13 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
/** Get the first {@link Instant} with this month/day/millis that is at or after the start. */
public Instant getNextInstanceAtOrAfter(Instant start) {
Instant withSameYear = toInstantWithYear(ZonedDateTime.ofInstant(start, UTC).getYear());
Instant withSameYear = toInstantWithYear(OffsetDateTime.ofInstant(start, UTC).getYear());
return isAtOrAfter(withSameYear, start) ? withSameYear : plusYears(withSameYear, 1);
}
/** Get the first {@link Instant} with this month/day/millis that is at or before the end. */
public Instant getLastInstanceBeforeOrAt(Instant end) {
Instant withSameYear = toInstantWithYear(ZonedDateTime.ofInstant(end, UTC).getYear());
Instant withSameYear = toInstantWithYear(OffsetDateTime.ofInstant(end, UTC).getYear());
return isBeforeOrAt(withSameYear, end) ? withSameYear : minusYears(withSameYear, 1);
}

View File

@@ -1,37 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import google.registry.model.eppcommon.Address;
import jakarta.persistence.Embeddable;
/**
* EPP Contact Address
*
* <p>This class is embedded inside the {@link PostalInfo} of an EPP contact to hold its address.
* The fields are all defined in parent class {@link Address}, but the subclass is still necessary
* to pick up the contact namespace.
*
* <p>This does not implement {@code Overlayable} because it is intended to be bulk replaced on
* update.
*
* @see PostalInfo
*/
@Embeddable
public class ContactAddress extends Address {
/** Builder for {@link ContactAddress}. */
public static class Builder extends Address.Builder<ContactAddress> {}
}

View File

@@ -1,30 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import google.registry.model.eppcommon.AuthInfo;
import jakarta.persistence.Embeddable;
import jakarta.xml.bind.annotation.XmlType;
/** A version of authInfo specifically for contacts. */
@Embeddable
@XmlType(namespace = "urn:ietf:params:xml:ns:contact-1.0")
public class ContactAuthInfo extends AuthInfo {
public static ContactAuthInfo create(PasswordAuth pw) {
ContactAuthInfo instance = new ContactAuthInfo();
instance.pw = pw;
return instance;
}
}

View File

@@ -1,198 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.util.CollectionUtils.nullToEmpty;
import com.google.common.collect.Maps;
import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.model.contact.PostalInfo.Type;
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
import google.registry.model.eppinput.ResourceCommand.ResourceUpdate;
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.List;
import java.util.Map;
/** A collection of (vestigial) Contact commands. */
public class ContactCommand {
/** The fields on "chgType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
@XmlTransient
public static class ContactCreateOrChange extends ImmutableObject
implements ResourceCreateOrChange<EppResource.Builder<?, ?>> {
/** Postal info for the contact. */
List<PostalInfo> postalInfo;
/** Contacts voice number. */
ContactPhoneNumber voice;
/** Contacts fax number. */
ContactPhoneNumber fax;
/** Contacts email address. */
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
String email;
/** Authorization info (aka transfer secret) of the contact. */
ContactAuthInfo authInfo;
/** Disclosure policy. */
Disclose disclose;
/** Helper method to move between the postal infos list and the individual getters. */
protected Map<Type, PostalInfo> getPostalInfosAsMap() {
// There can be no more than 2 postalInfos (enforced by the schema), and if there are 2 they
// must be of different types (not enforced). If the type is repeated, uniqueIndex will throw.
checkState(nullToEmpty(postalInfo).size() <= 2);
return Maps.uniqueIndex(nullToEmpty(postalInfo), PostalInfo::getType);
}
public ContactPhoneNumber getVoice() {
return voice;
}
public ContactPhoneNumber getFax() {
return fax;
}
public String getEmail() {
return email;
}
public ContactAuthInfo getAuthInfo() {
return authInfo;
}
public Disclose getDisclose() {
return disclose;
}
public PostalInfo getInternationalizedPostalInfo() {
return getPostalInfosAsMap().get(Type.INTERNATIONALIZED);
}
public PostalInfo getLocalizedPostalInfo() {
return getPostalInfosAsMap().get(Type.LOCALIZED);
}
}
/** An abstract contact command that contains authorization info. */
@XmlTransient
public static class AbstractContactAuthCommand extends AbstractSingleResourceCommand {
/** Authorization info used to validate if client has permissions to perform this operation. */
ContactAuthInfo authInfo;
@Override
public ContactAuthInfo getAuthInfo() {
return authInfo;
}
}
/**
* A create command for a (vestigial) Contact, mapping "createType" from <a
* href="http://tools.ietf.org/html/rfc5733">RFC5733</a>}.
*/
@XmlType(propOrder = {"contactId", "postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
@XmlRootElement
public static class Create extends ContactCreateOrChange
implements SingleResourceCommand, ResourceCreateOrChange<EppResource.Builder<?, ?>> {
/**
* Unique identifier for this contact.
*
* <p>This is only unique in the sense that for any given lifetime specified as the time range
* from (creationTime, deletionTime) there can only be one contact in the database with this id.
* However, there can be many contacts with the same id and non-overlapping lifetimes.
*/
@XmlElement(name = "id")
String contactId;
@Override
public String getTargetId() {
return contactId;
}
@Override
public ContactAuthInfo getAuthInfo() {
return authInfo;
}
}
/** A delete command for a (vestigial) Contact. */
@XmlRootElement
public static class Delete extends AbstractSingleResourceCommand {}
/** An info request for a (vestigial) Contact. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "authInfo"})
public static class Info extends AbstractContactAuthCommand {}
/** A check request for (vestigial) Contact. */
@XmlRootElement
public static class Check extends ResourceCheck {}
/** A transfer operation for a (vestigial) Contact. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "authInfo"})
public static class Transfer extends AbstractContactAuthCommand {}
/** An update to a (vestigial) Contact. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update
extends ResourceUpdate<Update.AddRemove, EppResource.Builder<?, ?>, Update.Change> {
@XmlElement(name = "chg")
protected Change innerChange;
@XmlElement(name = "add")
protected AddRemove innerAdd;
@XmlElement(name = "rem")
protected AddRemove innerRemove;
@Override
protected Change getNullableInnerChange() {
return innerChange;
}
@Override
protected AddRemove getNullableInnerAdd() {
return innerAdd;
}
@Override
protected AddRemove getNullableInnerRemove() {
return innerRemove;
}
/** The inner change type on a contact update command. */
public static class AddRemove extends ResourceUpdate.AddRemove {}
/** The inner change type on a contact update command. */
@XmlType(propOrder = {"postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
public static class Change extends ContactCreateOrChange {}
}
}

View File

@@ -1,140 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import com.google.auto.value.AutoValue;
import com.google.auto.value.AutoValue.CopyAnnotations;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppoutput.EppResponse.ResponseData;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.time.Instant;
import javax.annotation.Nullable;
/** The {@link ResponseData} returned for an EPP info flow on a contact. */
@XmlRootElement(name = "infData")
@XmlType(
propOrder = {
"contactId",
"repoId",
"statusValues",
"postalInfos",
"voiceNumber",
"faxNumber",
"emailAddress",
"currentSponsorRegistrarId",
"creationRegistrarId",
"creationTime",
"lastEppUpdateRegistrarId",
"lastEppUpdateTime",
"lastTransferTime",
"authInfo",
"disclose"
})
@AutoValue
@CopyAnnotations
public abstract class ContactInfoData implements ResponseData {
@XmlElement(name = "id")
abstract String getContactId();
@XmlElement(name = "roid")
abstract String getRepoId();
@XmlElement(name = "status")
abstract ImmutableSet<StatusValue> getStatusValues();
@XmlElement(name = "postalInfo")
abstract ImmutableList<PostalInfo> getPostalInfos();
@XmlElement(name = "voice")
@Nullable
abstract ContactPhoneNumber getVoiceNumber();
@XmlElement(name = "fax")
@Nullable
abstract ContactPhoneNumber getFaxNumber();
@XmlElement(name = "email")
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@Nullable
abstract String getEmailAddress();
@XmlElement(name = "clID")
abstract String getCurrentSponsorRegistrarId();
@XmlElement(name = "crID")
abstract String getCreationRegistrarId();
@XmlElement(name = "crDate")
abstract Instant getCreationTime();
@XmlElement(name = "upID")
@Nullable
abstract String getLastEppUpdateRegistrarId();
@XmlElement(name = "upDate")
@Nullable
abstract Instant getLastEppUpdateTime();
@XmlElement(name = "trDate")
@Nullable
abstract Instant getLastTransferTime();
@XmlElement(name = "authInfo")
@Nullable
abstract ContactAuthInfo getAuthInfo();
@XmlElement(name = "disclose")
@Nullable
abstract Disclose getDisclose();
/** Builder for {@link ContactInfoData}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setContactId(String contactId);
public abstract Builder setRepoId(String repoId);
public abstract Builder setStatusValues(ImmutableSet<StatusValue> statusValues);
public abstract Builder setPostalInfos(ImmutableList<PostalInfo> postalInfos);
public abstract Builder setVoiceNumber(@Nullable ContactPhoneNumber voiceNumber);
public abstract Builder setFaxNumber(@Nullable ContactPhoneNumber faxNumber);
public abstract Builder setEmailAddress(@Nullable String emailAddress);
public abstract Builder setCurrentSponsorRegistrarId(String currentSponsorRegistrarId);
public abstract Builder setCreationRegistrarId(String creationRegistrarId);
public abstract Builder setCreationTime(Instant creationTime);
public abstract Builder setLastEppUpdateRegistrarId(@Nullable String lastEppUpdateRegistrarId);
public abstract Builder setLastEppUpdateTime(@Nullable Instant lastEppUpdateTime);
public abstract Builder setLastTransferTime(@Nullable Instant lastTransferTime);
public abstract Builder setAuthInfo(@Nullable ContactAuthInfo authInfo);
public abstract Builder setDisclose(@Nullable Disclose disclose);
public abstract ContactInfoData build();
}
public static Builder newBuilder() {
return new AutoValue_ContactInfoData.Builder();
}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import google.registry.model.eppcommon.PhoneNumber;
import jakarta.persistence.Embeddable;
/**
* EPP Contact Phone Number
*
* <p>This class is embedded inside a (vestigial) Contact to hold the phone number of an EPP
* contact. The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is
* still necessary to pick up the contact namespace.
*/
@Embeddable
public class ContactPhoneNumber extends PhoneNumber {
/** Builder for {@link ContactPhoneNumber}. */
public static class Builder extends PhoneNumber.Builder<ContactPhoneNumber> {}
}

View File

@@ -1,137 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
import google.registry.model.eppcommon.PresenceMarker;
import google.registry.persistence.converter.PostalInfoChoiceListUserType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlType;
import java.io.Serializable;
import java.util.List;
import org.hibernate.annotations.Type;
/** The "discloseType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
@Embeddable
@XmlType(propOrder = {"name", "org", "addr", "voice", "fax", "email"})
public class Disclose extends ImmutableObject implements UnsafeSerializable {
@Type(PostalInfoChoiceListUserType.class)
List<PostalInfoChoice> name;
@Type(PostalInfoChoiceListUserType.class)
List<PostalInfoChoice> org;
@Type(PostalInfoChoiceListUserType.class)
List<PostalInfoChoice> addr;
@Embedded PresenceMarker voice;
@Embedded PresenceMarker fax;
@Embedded PresenceMarker email;
@XmlAttribute
Boolean flag;
public ImmutableList<PostalInfoChoice> getNames() {
return nullToEmptyImmutableCopy(name);
}
public ImmutableList<PostalInfoChoice> getOrgs() {
return nullToEmptyImmutableCopy(org);
}
public ImmutableList<PostalInfoChoice> getAddrs() {
return nullToEmptyImmutableCopy(addr);
}
public PresenceMarker getVoice() {
return voice;
}
public PresenceMarker getFax() {
return fax;
}
public PresenceMarker getEmail() {
return email;
}
public Boolean getFlag() {
return flag;
}
/** The "intLocType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
public static class PostalInfoChoice extends ImmutableObject implements Serializable {
@XmlAttribute
PostalInfo.Type type;
public PostalInfo.Type getType() {
return type;
}
public static PostalInfoChoice create(PostalInfo.Type type) {
PostalInfoChoice instance = new PostalInfoChoice();
instance.type = type;
return instance;
}
}
/** A builder for {@link Disclose} since it is immutable. */
public static class Builder extends Buildable.Builder<Disclose> {
public Builder setNames(ImmutableList<PostalInfoChoice> names) {
getInstance().name = names;
return this;
}
public Builder setOrgs(ImmutableList<PostalInfoChoice> orgs) {
getInstance().org = orgs;
return this;
}
public Builder setAddrs(ImmutableList<PostalInfoChoice> addrs) {
getInstance().addr = addrs;
return this;
}
public Builder setVoice(PresenceMarker voice) {
getInstance().voice = voice;
return this;
}
public Builder setFax(PresenceMarker fax) {
getInstance().fax = fax;
return this;
}
public Builder setEmail(PresenceMarker email) {
getInstance().email = email;
return this;
}
public Builder setFlag(boolean flag) {
getInstance().flag = flag;
return this;
}
}
}

View File

@@ -1,124 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.contact;
import static com.google.common.base.Preconditions.checkState;
import google.registry.model.Buildable;
import google.registry.model.Buildable.Overlayable;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlEnumValue;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.adapters.NormalizedStringAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Optional;
/**
* Implementation of both "postalInfoType" and "chgPostalInfoType" from <a href=
* "http://tools.ietf.org/html/rfc5733">RFC5733</a>.
*/
@Embeddable
@XmlType(propOrder = {"name", "org", "address", "type"})
public class PostalInfo extends ImmutableObject
implements Overlayable<PostalInfo>, UnsafeSerializable {
/** The type of the address, either localized or international. */
public enum Type {
@XmlEnumValue("loc")
LOCALIZED,
@XmlEnumValue("int")
INTERNATIONALIZED
}
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
String name;
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
String org;
@XmlElement(name = "addr")
ContactAddress address;
@Enumerated(EnumType.STRING)
@XmlAttribute
Type type;
public String getName() {
return name;
}
public String getOrg() {
return org;
}
public ContactAddress getAddress() {
return address;
}
public Type getType() {
return type;
}
@Override
public PostalInfo overlay(PostalInfo source) {
// Don't overlay the type field, as that should never change.
checkState(source.type == null || source.type == type);
return asBuilder()
.setName(Optional.ofNullable(source.getName()).orElse(name))
.setOrg(Optional.ofNullable(source.getOrg()).orElse(org))
.setAddress(Optional.ofNullable(source.getAddress()).orElse(address))
.build();
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** A builder for constructing {@link PostalInfo}, since its changes get overlayed. */
public static class Builder extends Buildable.Builder<PostalInfo> {
public Builder() {}
private Builder(PostalInfo instance) {
super(instance);
}
public Builder setName(String name) {
getInstance().name = name;
return this;
}
public Builder setOrg(String org) {
getInstance().org = org;
return this;
}
public Builder setAddress(ContactAddress address) {
getInstance().address = address;
return this;
}
public Builder setType(Type type) {
getInstance().type = type;
return this;
}
}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
@XmlSchema(
namespace = "urn:ietf:params:xml:ns:contact-1.0",
xmlns = @XmlNs(prefix = "contact", namespaceURI = "urn:ietf:params:xml:ns:contact-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
})
package google.registry.model.contact;
import google.registry.xml.UtcInstantAdapter;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlNs;
import jakarta.xml.bind.annotation.XmlNsForm;
import jakarta.xml.bind.annotation.XmlSchema;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

View File

@@ -14,7 +14,6 @@
package google.registry.model.domain;
import google.registry.model.EppResource;
import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName;
@@ -145,6 +144,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
// TODO(b/188044616): Determine why Eager loading doesn't work here.
Hibernate.initialize(dsData);
Hibernate.initialize(gracePeriods);
Hibernate.initialize(nsHosts);
}
@Override

View File

@@ -246,7 +246,7 @@ public class DomainBase extends EppResource {
*
* <p>When a domain is scheduled to not autorenew, this field is set to the current value of its
* {@link #registrationExpirationTime}, after which point the next invocation of a periodic
* cronjob will explicitly delete the domain. This field is a DateTime and not a boolean because
* cronjob will explicitly delete the domain. This field is an Instant and not a boolean because
* of edge cases that occur during the autorenew grace period. We need to be able to tell the
* difference domains that have reached their life and must be deleted now, and domains that
* happen to be in the autorenew grace period now but should be deleted in roughly a year.
@@ -358,13 +358,7 @@ public class DomainBase extends EppResource {
return nullToEmptyImmutableCopy(nsHosts);
}
// Hibernate needs this in order to populate nsHosts but no one else should ever use it
@SuppressWarnings("unused")
private void setNsHosts(Set<VKey<Host>> nsHosts) {
this.nsHosts = forceEmptyToNull(nsHosts);
}
// Note: for the two methods below, how we wish to treat the Hibernate setters depends on the
// Note: for the three methods below, how we wish to treat the Hibernate setters depends on the
// current state of the object and what's passed in. The key principle is that we wish to maintain
// the link between parent and child objects, meaning that we should keep around whichever of the
// two sets (the parameter vs the class variable and clear/populate that as appropriate).
@@ -373,6 +367,20 @@ public class DomainBase extends EppResource {
// an exception "A collection with cascade=”all-delete-orphan” was no longer referenced by the
// owning entity instance". See https://stackoverflow.com/questions/5587482 for more details.
// Hibernate needs this in order to populate nsHosts but no one else should ever use it
@SuppressWarnings("unused")
private void setNsHosts(Set<VKey<Host>> nsHosts) {
if (this.nsHosts instanceof PersistentSet) {
Set<VKey<Host>> nonNullNsHosts = nullToEmpty(nsHosts);
this.nsHosts.retainAll(nonNullNsHosts);
this.nsHosts.addAll(nonNullNsHosts);
} else if (nsHosts instanceof PersistentSet) {
this.nsHosts = nsHosts;
} else {
this.nsHosts = forceEmptyToNull(nsHosts);
}
}
// Hibernate needs this in order to populate gracePeriods but no one else should ever use it
@SuppressWarnings("unused")
private void setInternalGracePeriods(Set<GracePeriod> gracePeriods) {
@@ -642,6 +650,7 @@ public class DomainBase extends EppResource {
// cascadable operations and orphan removal.
newDomain.gracePeriods =
newDomain.gracePeriods == null ? ImmutableSet.of() : newDomain.gracePeriods;
newDomain.nsHosts = newDomain.nsHosts == null ? ImmutableSet.of() : newDomain.nsHosts;
newDomain.dsData =
newDomain.dsData == null
? ImmutableSet.of()

View File

@@ -17,7 +17,6 @@ package google.registry.model.domain;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Sets.difference;
import static google.registry.util.CollectionUtils.difference;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.CollectionUtils.nullSafeImmutableCopy;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
@@ -28,8 +27,11 @@ import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.flows.domain.DomainFlowUtils.RegistrantProhibitedException;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.Buildable;
import google.registry.model.ForeignKeyUtils;
import google.registry.model.ImmutableObject;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
@@ -37,6 +39,8 @@ import google.registry.model.eppinput.ResourceCommand.ResourceUpdate;
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElementWrapper;
@@ -68,10 +72,10 @@ public class DomainCommand {
throws InvalidReferencesException, ParameterValuePolicyErrorException;
}
/** The fields on "chgType" from <a href="http://tools.ietf.org/html/rfc5731">RFC5731</a>. */
/** The fields on "chgType" from <a href="https://tools.ietf.org/html/rfc5731">RFC5731</a>. */
@XmlTransient
public static class DomainCreateOrChange<B extends Domain.Builder> extends ImmutableObject
implements ResourceCreateOrChange<B> {
public abstract static class DomainCreateOrChange<B extends Domain.Builder>
extends ImmutableObject implements ResourceCreateOrChange<B> {
/** The contactId of the registrant who registered this domain. */
@XmlElement(name = "registrant")
@@ -92,9 +96,10 @@ public class DomainCommand {
/**
* A create command for a {@link Domain}, mapping "createType" from <a
* href="http://tools.ietf.org/html/rfc5731">RFC5731</a>.
* href="https://tools.ietf.org/html/rfc5731">RFC5731</a>.
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
propOrder = {
"domainName",
@@ -147,17 +152,12 @@ public class DomainCommand {
return nullToEmptyImmutableCopy(nameservers);
}
@Override
public DomainAuthInfo getAuthInfo() {
return authInfo;
}
/** Creates a copy of this {@link Create} with hard links to hosts and contacts. */
@Override
public Create cloneAndLinkReferences(Instant now)
throws InvalidReferencesException, ParameterValuePolicyErrorException {
Create clone = clone(this);
clone.nameservers = linkHosts(clone.nameserverHostNames, now);
clone.nameservers = linkHosts(nullSafeImmutableCopy(clone.nameserverHostNames), now);
if (registrantContactId != null) {
throw new RegistrantProhibitedException();
}
@@ -166,14 +166,65 @@ public class DomainCommand {
}
return clone;
}
/** Builder for {@link Create}. */
public static class Builder extends Buildable.Builder<Create> {
public Builder setDomainName(String domainName) {
getInstance().domainName = domainName;
return this;
}
public Builder setPeriod(Period period) {
getInstance().period = period;
return this;
}
public Builder setNameserverHostNames(ImmutableSet<String> nameserverHostNames) {
getInstance().nameserverHostNames =
isNullOrEmpty(nameserverHostNames) ? null : nameserverHostNames;
return this;
}
public Builder setForeignKeyedDesignatedContacts(
ImmutableSet<ForeignKeyedDesignatedContact> foreignKeyedDesignatedContacts) {
getInstance().foreignKeyedDesignatedContacts =
isNullOrEmpty(foreignKeyedDesignatedContacts) ? null : foreignKeyedDesignatedContacts;
return this;
}
public Builder setRegistrant(String registrant) {
getInstance().registrantContactId = registrant;
return this;
}
public Builder setAuthInfo(DomainAuthInfo authInfo) {
getInstance().authInfo = authInfo;
return this;
}
}
}
/** A delete command for a {@link Domain}. */
@XmlRootElement
public static class Delete extends AbstractSingleResourceCommand {}
@XmlAccessorType(XmlAccessType.FIELD)
public static class Delete extends AbstractSingleResourceCommand {
@XmlElement(name = "name")
String name;
@Override
public String getTargetId() {
return name;
}
@Override
public void setTargetId(String targetId) {
this.name = targetId;
}
}
/** An info request for a {@link Domain}. */
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Info extends ImmutableObject implements SingleResourceCommand {
/** The name of the domain to look up, and an attribute specifying the host lookup type. */
@@ -226,7 +277,7 @@ public class DomainCommand {
}
@Override
public DomainAuthInfo getAuthInfo() {
public AuthInfo getAuthInfo() {
return authInfo;
}
}
@@ -237,12 +288,27 @@ public class DomainCommand {
/** A renew command for a {@link Domain}. */
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"name", "currentExpirationDate", "period"})
public static class Renew extends AbstractSingleResourceCommand {
@XmlElement(name = "name")
String name;
@Override
public String getTargetId() {
return name;
}
@Override
public void setTargetId(String targetId) {
this.name = targetId;
}
@XmlElement(name = "curExpDate")
LocalDate currentExpirationDate;
/** The period that this domain's state was set to last for. */
Period period;
@XmlElement Period period;
public LocalDate getCurrentExpirationDate() {
return currentExpirationDate;
@@ -251,13 +317,46 @@ public class DomainCommand {
public Period getPeriod() {
return firstNonNull(period, DEFAULT_PERIOD);
}
/** Builder for {@link Renew}. */
public static class Builder extends Buildable.Builder<Renew> {
public Builder setTargetId(String targetId) {
getInstance().setTargetId(targetId);
return this;
}
public Builder setCurrentExpirationDate(LocalDate currentExpirationDate) {
getInstance().currentExpirationDate = currentExpirationDate;
return this;
}
public Builder setPeriod(Period period) {
getInstance().period = period;
return this;
}
}
}
/** A transfer operation for a {@link Domain}. */
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"name", "period", "authInfo"})
public static class Transfer extends AbstractSingleResourceCommand {
@XmlElement(name = "name")
String name;
@Override
public String getTargetId() {
return name;
}
@Override
public void setTargetId(String targetId) {
this.name = targetId;
}
/** The period to extend this domain's registration upon completion of the transfer. */
Period period;
@XmlElement Period period;
/** Authorization info used to validate if client has permissions to perform this operation. */
DomainAuthInfo authInfo;
@@ -267,25 +366,40 @@ public class DomainCommand {
}
@Override
public DomainAuthInfo getAuthInfo() {
public AuthInfo getAuthInfo() {
return authInfo;
}
}
/** An update to a {@link Domain}. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update extends ResourceUpdate<Update.AddRemove, Domain.Builder, Update.Change>
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"name", "innerAdd", "innerRemove", "innerChange"})
public static class Update
extends ResourceUpdate<Update.DomainAddRemove, Domain.Builder, Update.Change>
implements CreateOrUpdate<Update> {
@XmlElement(name = "name")
String name;
@Override
public String getTargetId() {
return name;
}
@Override
public void setTargetId(String targetId) {
this.name = targetId;
}
@XmlElement(name = "chg")
protected Change innerChange;
@XmlElement(name = "add")
protected AddRemove innerAdd;
protected DomainAddRemove innerAdd;
@XmlElement(name = "rem")
protected AddRemove innerRemove;
protected DomainAddRemove innerRemove;
@Override
protected Change getNullableInnerChange() {
@@ -293,25 +407,49 @@ public class DomainCommand {
}
@Override
protected AddRemove getNullableInnerAdd() {
protected DomainAddRemove getNullableInnerAdd() {
return innerAdd;
}
@Override
protected AddRemove getNullableInnerRemove() {
protected DomainAddRemove getNullableInnerRemove() {
return innerRemove;
}
public boolean noChangesPresent() {
AddRemove emptyAddRemove = new AddRemove();
DomainAddRemove emptyAddRemove = new DomainAddRemove();
return emptyAddRemove.equals(getInnerAdd())
&& emptyAddRemove.equals(getInnerRemove())
&& new Change().equals(getInnerChange());
}
/** Builder for {@link Update}. */
public static class Builder extends Buildable.Builder<Update> {
public Builder setTargetId(String targetId) {
getInstance().setTargetId(targetId);
return this;
}
public Builder setInnerAdd(DomainAddRemove innerAdd) {
getInstance().innerAdd = innerAdd;
return this;
}
public Builder setInnerRemove(DomainAddRemove innerRemove) {
getInstance().innerRemove = innerRemove;
return this;
}
public Builder setInnerChange(Change innerChange) {
getInstance().innerChange = innerChange;
return this;
}
}
/** The inner change type on a domain update command. */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"nameserverHostNames", "foreignKeyedDesignatedContacts", "statusValues"})
public static class AddRemove extends ResourceUpdate.AddRemove {
public static class DomainAddRemove extends ResourceUpdate.AddRemove {
/** Fully qualified host names of the hosts that are the nameservers for the domain. */
@XmlElementWrapper(name = "ns")
@XmlElement(name = "hostObj")
@@ -324,6 +462,25 @@ public class DomainCommand {
@XmlElement(name = "contact")
Set<ForeignKeyedDesignatedContact> foreignKeyedDesignatedContacts;
@XmlElement(name = "status")
Set<StatusValue> statusValues;
public boolean isEmpty() {
return isNullOrEmpty(nameserverHostNames)
&& isNullOrEmpty(foreignKeyedDesignatedContacts)
&& isNullOrEmpty(statusValues);
}
@Override
public void setStatusValues(ImmutableSet<StatusValue> statusValues) {
this.statusValues = statusValues;
}
@Override
public ImmutableSet<StatusValue> getStatusValues() {
return nullToEmptyImmutableCopy(statusValues);
}
public ImmutableSet<String> getNameserverHostNames() {
return nullSafeImmutableCopy(nameserverHostNames);
}
@@ -332,11 +489,25 @@ public class DomainCommand {
return nullToEmptyImmutableCopy(nameservers);
}
/** Creates a copy of this {@link AddRemove} with hard links to hosts and contacts. */
private AddRemove cloneAndLinkReferences(Instant now)
/** Builder for {@link DomainAddRemove}. */
public static class Builder extends Buildable.Builder<DomainAddRemove> {
public Builder setNameserverHostNames(ImmutableSet<String> nameserverHostNames) {
getInstance().nameserverHostNames =
isNullOrEmpty(nameserverHostNames) ? null : nameserverHostNames;
return this;
}
public Builder setStatusValues(ImmutableSet<StatusValue> statusValues) {
getInstance().statusValues = isNullOrEmpty(statusValues) ? null : statusValues;
return this;
}
}
/** Creates a copy of this {@link DomainAddRemove} with hard links to hosts and contacts. */
private DomainAddRemove cloneAndLinkReferences(Instant now)
throws InvalidReferencesException, ContactsProhibitedException {
AddRemove clone = clone(this);
clone.nameservers = linkHosts(clone.nameserverHostNames, now);
DomainAddRemove clone = clone(this);
clone.nameservers = linkHosts(nullSafeImmutableCopy(clone.nameserverHostNames), now);
if (!isNullOrEmpty(foreignKeyedDesignatedContacts)) {
throw new ContactsProhibitedException();
}
@@ -345,8 +516,17 @@ public class DomainCommand {
}
/** The inner change type on a domain update command. */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"registrantContactId", "authInfo"})
public static class Change extends DomainCreateOrChange<Domain.Builder> {
/** Builder for {@link Change}. */
public static class Builder extends Buildable.Builder<Change> {
public Builder setAuthInfo(DomainAuthInfo authInfo) {
getInstance().authInfo = authInfo;
return this;
}
}
Change cloneAndLinkReferences() throws RegistrantProhibitedException {
Change clone = clone(this);
if (clone.registrantContactId != null) {
@@ -373,7 +553,7 @@ public class DomainCommand {
}
}
private static Set<VKey<Host>> linkHosts(Set<String> hostNames, Instant now)
private static ImmutableSet<VKey<Host>> linkHosts(ImmutableSet<String> hostNames, Instant now)
throws InvalidReferencesException {
if (hostNames == null) {
return null;
@@ -383,7 +563,7 @@ public class DomainCommand {
/** Loads host keys to cached EPP resources by their foreign keys. */
private static ImmutableMap<String, VKey<Host>> loadByForeignKeysCached(
Set<String> foreignKeys, Instant now) throws InvalidReferencesException {
ImmutableSet<String> foreignKeys, Instant now) throws InvalidReferencesException {
ImmutableMap<String, VKey<Host>> fks =
ForeignKeyUtils.loadKeysByCacheIfEnabled(Host.class, foreignKeys, now);
if (!fks.keySet().equals(foreignKeys)) {
@@ -394,14 +574,14 @@ public class DomainCommand {
}
/** Exception to throw when referenced objects don't exist. */
public static class InvalidReferencesException extends Exception {
public static class InvalidReferencesException extends ParameterValuePolicyErrorException {
private final ImmutableSet<String> foreignKeys;
private final Class<?> type;
InvalidReferencesException(Class<?> type, ImmutableSet<String> foreignKeys) {
public InvalidReferencesException(Class<?> type, Set<String> foreignKeys) {
super(String.format("Invalid %s reference IDs: %s", type.getSimpleName(), foreignKeys));
this.type = checkNotNull(type);
this.foreignKeys = foreignKeys;
this.foreignKeys = nullToEmptyImmutableCopy(foreignKeys);
}
public ImmutableSet<String> getForeignKeys() {

View File

@@ -14,7 +14,6 @@
package google.registry.model.domain;
import google.registry.model.eppoutput.EppResponse.ResponseData;
import google.registry.xml.UtcInstantAdapter;
import jakarta.xml.bind.annotation.XmlElement;

View File

@@ -14,7 +14,6 @@
package google.registry.model.domain;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
import google.registry.model.billing.BillingEvent;

View File

@@ -31,8 +31,8 @@ import jakarta.xml.bind.annotation.XmlValue;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.Period;
import java.util.stream.Stream;
import org.joda.time.Period;
/** Base class for the fee and credit types. */
@XmlTransient

View File

@@ -15,27 +15,45 @@
package google.registry.model.domain.fee;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import google.registry.model.Buildable;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.Period;
/**
* A fee, in currency units specified elsewhere in the xml, with type of the fee an optional fee
* description.
* A fee, in currency units specified elsewhere in the XML, with a type and an optional description.
*/
public class Fee extends BaseFee {
public static final ImmutableSet<String> FEE_EXTENSION_URIS =
ImmutableSet.of(
ServiceExtension.FEE_1_00.getUri(),
ServiceExtension.FEE_0_12.getUri(),
ServiceExtension.FEE_0_11.getUri(),
ServiceExtension.FEE_0_6.getUri());
@Override
public Fee clone() {
return (Fee) super.clone();
}
/** Creates a Fee for the given cost and type with the default description. */
public static Fee create(
BigDecimal cost, FeeType type, boolean isPremium, Object... descriptionArgs) {
checkArgumentNotNull(type, "Must specify the type of the fee");
return createWithCustomDescription(
cost, type, isPremium, type.renderDescription(descriptionArgs));
checkArgumentNotNull(cost, "Cost cannot be null");
checkArgument(cost.signum() >= 0, "Cost must be a non-negative number");
Fee instance = new Fee();
instance.cost = cost;
instance.type = type;
instance.isPremium = isPremium;
instance.description = type.renderDescription(descriptionArgs);
return instance;
}
/** Creates a Fee for the given cost, type, and valid date range with the default description. */
@@ -50,22 +68,37 @@ public class Fee extends BaseFee {
return instance;
}
/** Creates a Fee for the given cost and type with a custom description. */
private static Fee createWithCustomDescription(
BigDecimal cost, FeeType type, boolean isPremium, String description) {
Fee instance = new Fee();
instance.cost = checkNotNull(cost);
checkArgument(instance.cost.signum() >= 0, "Cost must be a positive number");
instance.type = checkNotNull(type);
instance.isPremium = isPremium;
instance.description = description;
return instance;
}
/** Builder for {@link Fee}. */
public static class Builder extends Buildable.Builder<Fee> {
public static final ImmutableSet<String> FEE_EXTENSION_URIS =
ImmutableSet.of(
ServiceExtension.FEE_1_00.getUri(),
ServiceExtension.FEE_0_12.getUri(),
ServiceExtension.FEE_0_11.getUri(),
ServiceExtension.FEE_0_6.getUri());
/** Sets the cost of the fee. */
public Builder setCost(BigDecimal cost) {
getInstance().cost = cost;
return this;
}
/** Sets the description of the fee. */
public Builder setDescription(String description) {
getInstance().description = description;
return this;
}
/** Sets whether the fee is refundable. */
public Builder setRefundable(Boolean refundable) {
getInstance().refundable = refundable;
return this;
}
/** Sets the grace period of the fee. */
public Builder setGracePeriod(Period gracePeriod) {
getInstance().gracePeriod = gracePeriod;
return this;
}
/** Sets when the fee is applied. */
public Builder setApplied(AppliedType applied) {
getInstance().applied = applied;
return this;
}
}
}

View File

@@ -34,4 +34,3 @@ public abstract class FeeCheckResponseExtensionItem extends FeeQueryResponseExte
}
}
}

View File

@@ -78,6 +78,10 @@ public abstract class FeeQueryCommandExtensionItem extends ImmutableObject {
/** The period for the command being checked. */
Period period;
public void setPeriod(Period period) {
this.period = period;
}
/**
* Three-character ISO4217 currency code.
*

View File

@@ -30,7 +30,7 @@ public abstract class FeeTransformCommandExtension
extends ImmutableObject implements CommandExtension {
/** The currency of the fee. */
CurrencyUnit currency;
@XmlElement public CurrencyUnit currency;
/**
* The magnitude of the fee, in the specified units, with an optional description.
@@ -38,7 +38,7 @@ public abstract class FeeTransformCommandExtension
* <p>This is a list because a single operation can involve multiple fees.
*/
@XmlElement(name = "fee")
List<Fee> fees;
public List<Fee> fees;
public CurrencyUnit getCurrency() {
return currency;

View File

@@ -31,7 +31,7 @@ import org.joda.money.CurrencyUnit;
public class FeeTransformResponseExtension extends ImmutableObject implements ResponseExtension {
/** The currency of the fee. */
CurrencyUnit currency;
@XmlElement CurrencyUnit currency;
/**
* The magnitude of the fee, in the specified units, with an optional description.
@@ -63,12 +63,12 @@ public class FeeTransformResponseExtension extends ImmutableObject implements Re
}
public Builder setFees(List<Fee> fees) {
getInstance().fees = fees;
getInstance().fees = forceEmptyToNull(nullToEmptyImmutableCopy(fees));
return this;
}
public Builder setCredits(List<Credit> credits) {
getInstance().credits = forceEmptyToNull(credits);
getInstance().credits = forceEmptyToNull(nullToEmptyImmutableCopy(credits));
return this;
}
}

View File

@@ -14,6 +14,7 @@
package google.registry.model.domain.fee06;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import google.registry.model.domain.fee.FeeExtensionCommandDescriptor;
import jakarta.xml.bind.annotation.XmlType;
@@ -33,6 +34,16 @@ public class FeeCheckCommandExtensionItemV06 extends FeeCheckCommandExtensionIte
/** The command being checked. */
FeeExtensionCommandDescriptor command;
public static FeeCheckCommandExtensionItemV06 create(
String name, CurrencyUnit currency, FeeExtensionCommandDescriptor command, Period period) {
FeeCheckCommandExtensionItemV06 instance = new FeeCheckCommandExtensionItemV06();
instance.name = name;
instance.currency = currency;
instance.command = command;
instance.setPeriod(period);
return instance;
}
/** The name of the command being checked. */
@Override
public CommandName getCommandName() {

View File

@@ -25,16 +25,22 @@ import jakarta.xml.bind.annotation.XmlRootElement;
import java.util.List;
import org.joda.money.CurrencyUnit;
/** Version 0.6 of the fee extension that may be present on domain check commands. */
/**
* An XML data object that represents version 0.6 of the fee extension that may be present on EPP
* domain check commands.
*/
@XmlRootElement(name = "check")
public class FeeCheckCommandExtensionV06 extends ImmutableObject
implements FeeCheckCommandExtension<
FeeCheckCommandExtensionItemV06,
FeeCheckResponseExtensionV06> {
FeeCheckCommandExtensionItemV06, FeeCheckResponseExtensionV06> {
@XmlElement(name = "domain")
List<FeeCheckCommandExtensionItemV06> items;
public void setItems(ImmutableList<FeeCheckCommandExtensionItemV06> items) {
this.items = items;
}
@Override
public CurrencyUnit getCurrency() {
return null; // This version of the fee extension doesn't specify a top-level currency.

View File

@@ -15,13 +15,20 @@
package google.registry.model.domain.fee06;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable;
import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeCreateCommandExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/** A fee extension that may be present on domain create commands. */
/**
* An XML data object that represents a fee extension that may be present on EPP domain create
* commands.
*/
@XmlRootElement(name = "create")
@XmlType(propOrder = {"currency", "fees"})
public class FeeCreateCommandExtensionV06 extends FeeCreateCommandExtension {
@@ -31,12 +38,23 @@ public class FeeCreateCommandExtensionV06 extends FeeCreateCommandExtension {
return new FeeTransformResponseExtension.Builder(new FeeCreateResponseExtensionV06());
}
/**
* This method is overridden and not annotated for JAXB because this version of the extension
* doesn't support the "credit" field.
*/
/** This version of the extension doesn't support the "credit" field. */
@Override
@XmlTransient
public ImmutableList<Credit> getCredits() {
return ImmutableList.of();
}
/** Builder for {@link FeeCreateCommandExtensionV06}. */
public static class Builder extends Buildable.Builder<FeeCreateCommandExtensionV06> {
public Builder setCurrency(CurrencyUnit currency) {
getInstance().currency = currency;
return this;
}
public Builder setFees(ImmutableList<Fee> fees) {
getInstance().fees = fees;
return this;
}
}
}

View File

@@ -14,8 +14,6 @@
package google.registry.model.domain.fee06;
import com.google.common.collect.ImmutableList;
import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
@@ -25,12 +23,5 @@ import jakarta.xml.bind.annotation.XmlType;
* domain create commands.
*/
@XmlRootElement(name = "creData")
@XmlType(propOrder = {"currency", "fees"})
public class FeeCreateResponseExtensionV06 extends FeeTransformResponseExtension {
/** This version of the extension doesn't support the "credit" field. */
@Override
public ImmutableList<Credit> getCredits() {
return ImmutableList.of();
}
}
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeCreateResponseExtensionV06 extends FeeTransformResponseExtension {}

View File

@@ -20,7 +20,7 @@ import jakarta.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
* domain delete commands.
*/
@XmlRootElement(name = "delData")
@XmlType(propOrder = {"currency", "fees", "credits"})

Some files were not shown because too many files have changed in this diff Show More