Add XAP registrar flag and drop DB defaults (#3222)

Expose the --expiry_access_period_enabled CLI flag on registrar mutation
commands and drop temporary database-level default constraints for XAP.

Specifically:
- Expose the --expiry_access_period_enabled parameter in
  CreateOrUpdateRegistrarCommand and pass it to
  Registrar.Builder.setExpiryAccessPeriodEnabled.
- Add expiryAccessPeriodTransitions with default DISABLED to example.yaml.
- Add unit tests for --expiry_access_period_enabled in
  CreateRegistrarCommandTest and UpdateRegistrarCommandTest.
- Add Flyway migrations V229 and V230 to drop the temporary database-level
  DEFAULT constraints on Tld.expiry_access_period_transitions and
  Registrar.expiry_access_period_enabled per db/README.md.
- Regenerate flyway.txt, nomulus.golden.sql, and ER diagrams.

TAG=agy
BUG=http://b/437398822
This commit is contained in:
Ben McIlwain
2026-08-31 16:36:29 +00:00
committed by GitHub
parent 275c65115b
commit 36dd7fbe06
10 changed files with 117 additions and 20 deletions
@@ -27,6 +27,8 @@ eapFeeSchedule:
currency: "USD"
amount: 0.00
escrowEnabled: false
expiryAccessPeriodTransitions:
"1970-01-01T00:00:00.000Z": "DISABLED"
idnTables: []
invoicingEnabled: false
lordnUsername: null
@@ -234,6 +234,13 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
arity = 1)
private Boolean registryLockAllowed;
@Nullable
@Parameter(
names = "--expiry_access_period_enabled",
description = "Whether this registrar is enabled for the Expiry Access Period",
arity = 1)
private Boolean expiryAccessPeriodEnabled;
@Nullable
@Parameter(
names = "--drive_folder_id",
@@ -384,6 +391,8 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
Optional.ofNullable(blockPremiumNames).ifPresent(builder::setBlockPremiumNames);
Optional.ofNullable(contactsRequireSyncing).ifPresent(builder::setContactsRequireSyncing);
Optional.ofNullable(registryLockAllowed).ifPresent(builder::setRegistryLockAllowed);
Optional.ofNullable(expiryAccessPeriodEnabled)
.ifPresent(builder::setExpiryAccessPeriodEnabled);
Optional.ofNullable(phonePasscode).ifPresent(builder::setPhonePasscode);
Optional.ofNullable(icannReferralEmail).ifPresent(builder::setIcannReferralEmail);
Optional.ofNullable(whoisServer).ifPresent(builder::setWhoisServer);
@@ -104,6 +104,7 @@ class CreateRegistrarCommandTest extends CommandTestCase<CreateRegistrarCommand>
assertThat(registrar.getLastUpdateTime()).isEqualTo(registrar.getCreationTime());
assertThat(registrar.getBlockPremiumNames()).isFalse();
assertThat(registrar.isRegistryLockAllowed()).isFalse();
assertThat(registrar.getExpiryAccessPeriodEnabled()).isFalse();
assertThat(registrar.getPoNumber()).isEmpty();
assertThat(registrar.getIcannReferralEmail()).isEqualTo("foo@bar.test");
@@ -890,6 +891,50 @@ class CreateRegistrarCommandTest extends CommandTestCase<CreateRegistrarCommand>
assertThat(registrar.get().isRegistryLockAllowed()).isFalse();
}
@Test
void testSuccess_expiryAccessPeriodEnabled() throws Exception {
runCommandForced(
"--name=blobio",
"--password=some_password",
"--registrar_type=REAL",
"--iana_id=8",
"--expiry_access_period_enabled=true",
"--passcode=01234",
"--icann_referral_email=foo@bar.test",
"--street=\"123 Fake St\"",
"--city Fakington",
"--state MA",
"--zip 00351",
"--cc US",
"clientz");
Optional<Registrar> registrar = Registrar.loadByRegistrarId("clientz");
assertThat(registrar).isPresent();
assertThat(registrar.get().getExpiryAccessPeriodEnabled()).isTrue();
}
@Test
void testSuccess_expiryAccessPeriodDisabled() throws Exception {
runCommandForced(
"--name=blobio",
"--password=some_password",
"--registrar_type=REAL",
"--iana_id=8",
"--expiry_access_period_enabled=false",
"--passcode=01234",
"--icann_referral_email=foo@bar.test",
"--street=\"123 Fake St\"",
"--city Fakington",
"--state MA",
"--zip 00351",
"--cc US",
"clientz");
Optional<Registrar> registrar = Registrar.loadByRegistrarId("clientz");
assertThat(registrar).isPresent();
assertThat(registrar.get().getExpiryAccessPeriodEnabled()).isFalse();
}
@Test
void testFailure_badPhoneNumber() {
ParameterException thrown =
@@ -563,6 +563,21 @@ class UpdateRegistrarCommandTest extends CommandTestCase<UpdateRegistrarCommand>
assertThat(loadRegistrar("NewRegistrar").isRegistryLockAllowed()).isFalse();
}
@Test
void testSuccess_expiryAccessPeriodEnabled() throws Exception {
assertThat(loadRegistrar("NewRegistrar").getExpiryAccessPeriodEnabled()).isFalse();
runCommandForced("--expiry_access_period_enabled=true", "NewRegistrar");
assertThat(loadRegistrar("NewRegistrar").getExpiryAccessPeriodEnabled()).isTrue();
}
@Test
void testSuccess_resetExpiryAccessPeriodEnabled() throws Exception {
persistResource(
loadRegistrar("NewRegistrar").asBuilder().setExpiryAccessPeriodEnabled(true).build());
runCommandForced("--expiry_access_period_enabled=false", "NewRegistrar");
assertThat(loadRegistrar("NewRegistrar").getExpiryAccessPeriodEnabled()).isFalse();
}
@Test
void testSuccess_unspecifiedBooleansArentChanged() throws Exception {
persistResource(
@@ -570,6 +585,7 @@ class UpdateRegistrarCommandTest extends CommandTestCase<UpdateRegistrarCommand>
.asBuilder()
.setBlockPremiumNames(true)
.setContactsRequireSyncing(true)
.setExpiryAccessPeriodEnabled(true)
.build());
// Make some unrelated change where we don't specify the flags for the booleans.
runCommandForced("NewRegistrar");
@@ -577,6 +593,7 @@ class UpdateRegistrarCommandTest extends CommandTestCase<UpdateRegistrarCommand>
Registrar reloadedRegistrar = loadRegistrar("NewRegistrar");
assertThat(reloadedRegistrar.getBlockPremiumNames()).isTrue();
assertThat(reloadedRegistrar.getContactsRequireSyncing()).isTrue();
assertThat(reloadedRegistrar.getExpiryAccessPeriodEnabled()).isTrue();
}
@Test
@@ -261,11 +261,11 @@ td.section {
</tr>
<tr>
<td class="property_name">generated on</td>
<td class="property_value">2026-08-12 15:34:00</td>
<td class="property_value">2026-08-27 21:08:38</td>
</tr>
<tr>
<td class="property_name">last flyway file</td>
<td id="lastFlywayFile" class="property_value">V228__hosthistory_repo_id_mod_time_idx.sql</td>
<td id="lastFlywayFile" class="property_value">V230__registrar_drop_xap_enabled_default.sql</td>
</tr>
</tbody>
</table>
@@ -273,7 +273,7 @@ td.section {
<p>&nbsp;</p>
<svg viewBox="0.00 0.00 4783.00 3613.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="erDiagram" style="overflow: hidden; width: 100%; height: 800px">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 3608.5)">
<title>SchemaCrawler_Diagram</title> <polygon fill="white" stroke="none" points="-4,4 -4,-3608.5 4778.75,-3608.5 4778.75,4 -4,4" /> <text xml:space="preserve" text-anchor="start" x="4535.5" y="-29.2" font-family="Helvetica,sans-Serif" font-size="14.00">generated by</text> <text xml:space="preserve" text-anchor="start" x="4618.25" y="-29.2" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 17.12.2</text> <text xml:space="preserve" text-anchor="start" x="4534.75" y="-9.45" font-family="Helvetica,sans-Serif" font-size="14.00">generated on</text> <text xml:space="preserve" text-anchor="start" x="4618.25" y="-9.45" font-family="Helvetica,sans-Serif" font-size="14.00">2026-08-12 15:34:00</text> <polygon fill="none" stroke="#888888" points="4531.75,-4 4531.75,-45.5 4766.75,-45.5 4766.75,-4 4531.75,-4" /> <!-- allocationtoken_a08ccbef -->
<title>SchemaCrawler_Diagram</title> <polygon fill="white" stroke="none" points="-4,4 -4,-3608.5 4778.75,-3608.5 4778.75,4 -4,4" /> <text xml:space="preserve" text-anchor="start" x="4535.5" y="-29.2" font-family="Helvetica,sans-Serif" font-size="14.00">generated by</text> <text xml:space="preserve" text-anchor="start" x="4618.25" y="-29.2" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 17.12.2</text> <text xml:space="preserve" text-anchor="start" x="4534.75" y="-9.45" font-family="Helvetica,sans-Serif" font-size="14.00">generated on</text> <text xml:space="preserve" text-anchor="start" x="4618.25" y="-9.45" font-family="Helvetica,sans-Serif" font-size="14.00">2026-08-27 21:08:38</text> <polygon fill="none" stroke="#888888" points="4531.75,-4 4531.75,-45.5 4766.75,-45.5 4766.75,-4 4531.75,-4" /> <!-- allocationtoken_a08ccbef -->
<g id="node1" class="node">
<title>allocationtoken_a08ccbef</title> <polygon fill="#e9c2f2" stroke="none" points="479.25,-1014.62 479.25,-1034.38 664.25,-1034.38 664.25,-1014.62 479.25,-1014.62" /> <text xml:space="preserve" text-anchor="start" x="481.25" y="-1020.08" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">public."AllocationToken"</text> <polygon fill="#e9c2f2" stroke="none" points="664.25,-1014.62 664.25,-1034.38 737.25,-1034.38 737.25,-1014.62 664.25,-1014.62" /> <text xml:space="preserve" text-anchor="start" x="698.5" y="-1019.08" font-family="Helvetica,sans-Serif" font-size="14.00">[table]</text> <text xml:space="preserve" text-anchor="start" x="481.25" y="-1000.33" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">token</text> <text xml:space="preserve" text-anchor="start" x="658.5" y="-999.33" font-family="Helvetica,sans-Serif" font-size="14.00"> </text> <text xml:space="preserve" text-anchor="start" x="666.25" y="-999.33" font-family="Helvetica,sans-Serif" font-size="14.00">text not null</text> <text xml:space="preserve" text-anchor="start" x="481.25" y="-979.58" font-family="Helvetica,sans-Serif" font-size="14.00">domain_name</text> <text xml:space="preserve" text-anchor="start" x="658.5" y="-979.58" font-family="Helvetica,sans-Serif" font-size="14.00"> </text> <text xml:space="preserve" text-anchor="start" x="666.25" y="-979.58" font-family="Helvetica,sans-Serif" font-size="14.00">text</text> <text xml:space="preserve" text-anchor="start" x="481.25" y="-959.83" font-family="Helvetica,sans-Serif" font-size="14.00">redemption_domain_repo_id</text> <text xml:space="preserve" text-anchor="start" x="658.5" y="-959.83" font-family="Helvetica,sans-Serif" font-size="14.00"> </text> <text xml:space="preserve" text-anchor="start" x="666.25" y="-959.83" font-family="Helvetica,sans-Serif" font-size="14.00">text</text> <text xml:space="preserve" text-anchor="start" x="481.25" y="-940.08" font-family="Helvetica,sans-Serif" font-size="14.00">token_type</text> <text xml:space="preserve" text-anchor="start" x="658.5" y="-940.08" font-family="Helvetica,sans-Serif" font-size="14.00"> </text> <text xml:space="preserve" text-anchor="start" x="666.25" y="-940.08" font-family="Helvetica,sans-Serif" font-size="14.00">text</text> <polygon fill="none" stroke="#888888" points="478.25,-934.62 478.25,-1035.38 738.25,-1035.38 738.25,-934.62 478.25,-934.62" />
</g>
File diff suppressed because one or more lines are too long
+2
View File
@@ -226,3 +226,5 @@ V225__user_registry_lock_email_address_index.sql
V226__tld_domain_name_index.sql
V227__domainhistory_repo_id_mod_time_idx.sql
V228__hosthistory_repo_id_mod_time_idx.sql
V229__tld_drop_xap_transitions_default.sql
V230__registrar_drop_xap_enabled_default.sql
@@ -0,0 +1,16 @@
-- 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.
ALTER TABLE "Tld"
ALTER COLUMN expiry_access_period_transitions DROP DEFAULT;
@@ -0,0 +1,16 @@
-- 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.
ALTER TABLE "Registrar"
ALTER COLUMN expiry_access_period_enabled DROP DEFAULT;
@@ -2,8 +2,8 @@
-- PostgreSQL database dump
--
-- Dumped from database version 17.10
-- Dumped by pg_dump version 17.10
-- Dumped from database version 17.4
-- Dumped by pg_dump version 17.4
SET statement_timeout = 0;
SET lock_timeout = 0;
@@ -856,7 +856,7 @@ CREATE TABLE public."Registrar" (
last_expiring_cert_notification_sent_date timestamp with time zone,
last_expiring_failover_cert_notification_sent_date timestamp with time zone,
last_poc_verification_date timestamp with time zone,
expiry_access_period_enabled boolean DEFAULT false NOT NULL
expiry_access_period_enabled boolean NOT NULL
);
@@ -1206,7 +1206,7 @@ CREATE TABLE public."Tld" (
breakglass_mode boolean DEFAULT false NOT NULL,
bsa_enroll_start_time timestamp with time zone,
create_billing_cost_transitions public.hstore NOT NULL,
expiry_access_period_transitions public.hstore DEFAULT '"1970-01-01T00:00:00.000Z"=>"DISABLED"'::public.hstore NOT NULL
expiry_access_period_transitions public.hstore NOT NULL
);