1
0
mirror of https://github.com/google/nomulus synced 2026-07-19 14:32:44 +00:00

Implement Expiry Access Period flows and billing (#3131)

This commit implements the second stage (Java ORM mappings and EPP flow
enforcement) of the Expiry Access Period (XAP) launch and opt-in mechanism,
completing the Two-PR deployment split mandated by db/README.md after the
Stage 1 database migrations (PR #3134) are live.

During XAP, a TLD charges a fee for domain registration during a timed period
after deletion. To prevent accidental charges, registrars must explicitly
opt in to participate in XAP registrations.

Specifically, this commit:
- Adds expiryAccessPeriodTransitions (a TimedTransitionProperty of
  ExpiryAccessPeriodMode) to Tld.java and ExpiryAccessPeriodModeTransitionUserType
  for mapping XAP mode schedules to PostgreSQL hstore columns.
- Adds expiryAccessPeriodEnabled to Registrar.java with getter, builder
  setter, and JSON map serialization, and regenerates db-schema.sql.generated.
- Enforces registrar opt-in in DomainCheckFlow: when an unallocated domain is
  in XAP and the querying registrar has not opted in, domain:check returns
  avail="0" with reason "Reserved".
- Enforces registrar opt-in in DomainCreateFlow: when attempting to register
  a domain in XAP without registrar opt-in, throws DomainReservedException
  (EPP error 2304 "Object status prohibits operation").
- Enforces explicit fee acknowledgment during XAP domain creation when the XAP
  fee is non-zero, throwing FeesRequiredDuringExpiryAccessPeriodException in
  DomainFlowUtils if omitted.
- Creates a one-time BillingEvent with Reason.FEE_EXPIRY_ACCESS when a domain
  is created during XAP with a non-zero fee, and adds getXapCost() to
  FeesAndCredits.
- Updates all test TLD YAML configurations and adds comprehensive unit and
  integration tests across DomainCheckFlowTest, DomainCreateFlowTest,
  DomainPricingLogicTest, and RegistrarTest.

TAG=agy
CONV=f2488c74-8b4a-43f1-9c22-d1dddbdbb4e0
BUG=http://b/437398822
This commit is contained in:
Ben McIlwain
2026-07-15 17:25:40 -04:00
committed by GitHub
parent 542084eb70
commit 192a7e6c4e
44 changed files with 1852 additions and 56 deletions
@@ -43,7 +43,7 @@
domain_repo_id text not null,
event_time timestamp(6) with time zone not null,
flags text[],
reason text not null check ((reason in ('CREATE','ERROR','FEE_EARLY_ACCESS','RENEW','RESTORE','SERVER_STATUS','TRANSFER'))),
reason text not null check ((reason in ('CREATE','ERROR','FEE_EARLY_ACCESS','FEE_EXPIRY_ACCESS','RENEW','RESTORE','SERVER_STATUS','TRANSFER'))),
domain_name text not null,
billing_event_id bigint,
billing_recurrence_id bigint,
@@ -58,7 +58,7 @@
domain_repo_id text not null,
event_time timestamp(6) with time zone not null,
flags text[],
reason text not null check ((reason in ('CREATE','ERROR','FEE_EARLY_ACCESS','RENEW','RESTORE','SERVER_STATUS','TRANSFER'))),
reason text not null check ((reason in ('CREATE','ERROR','FEE_EARLY_ACCESS','FEE_EXPIRY_ACCESS','RENEW','RESTORE','SERVER_STATUS','TRANSFER'))),
domain_name text not null,
allocation_token text,
billing_time timestamp(6) with time zone,
@@ -78,7 +78,7 @@
domain_repo_id text not null,
event_time timestamp(6) with time zone not null,
flags text[],
reason text not null check ((reason in ('CREATE','ERROR','FEE_EARLY_ACCESS','RENEW','RESTORE','SERVER_STATUS','TRANSFER'))),
reason text not null check ((reason in ('CREATE','ERROR','FEE_EARLY_ACCESS','FEE_EXPIRY_ACCESS','RENEW','RESTORE','SERVER_STATUS','TRANSFER'))),
domain_name text not null,
recurrence_end_time timestamp(6) with time zone,
recurrence_last_expansion timestamp(6) with time zone not null,
@@ -507,6 +507,7 @@
creation_time timestamp(6) with time zone not null,
drive_folder_id text,
email_address text,
expiry_access_period_enabled boolean not null,
failover_client_certificate text,
failover_client_certificate_hash text,
fax_number text,
@@ -646,6 +647,7 @@
drive_folder_id text,
eap_fee_schedule hstore not null,
escrow_enabled boolean not null,
expiry_access_period_transitions hstore not null,
idn_tables text[],
invoicing_enabled boolean not null,
lordn_username text,