Repository navigation
feat(M365_BUILDER)!: rewrite in Go and update the records to Microsoft's current requirements - #4936
Merged
Merged
Conversation
…t's current requirements Issue DNSControl#4809 asks for M365_BUILDER to be moved to Go and for its records to be brought up to date. This is not a bug-for-bug port. The JavaScript version generates records that no longer work, and carrying those into Go would mean shipping a new builder that is already wrong on the day it lands. The builder now lives in models/b_m365.go and follows the RecordBuilderFn signature. Builders receive record.args only, so the options object is moved out of the metadata list in pkg/js/helpers.js (m365Options), the same way CAA and R53_ALIAS use the third parameter of rawrecordBuilder. models/builders.go is unchanged. Every generated record now has an on/off switch and exactly one option that replaces its target, which is what makes the sovereign clouds, DANE-enabled tenants and the DKIM format of May 2025 configurable. BREAKING CHANGE: label now applies to every generated record, not just the MX. The Skype for Business records are reduced to the SIP federation SRV. The device management CNAME uses enterpriseenrollment-s. A TTL() modifier on the call is applied instead of ignored. Unknown options, wrong types and a first argument that is not the name the records are created under are errors. Nine option names that used to be ignored now take effect. See the migration table in documentation/language-reference/domain-modifiers/M365_BUILDER.md.
TomOnTime
approved these changes
Sep 26, 2026
Collaborator
|
Looks great! Thanks for porting this to Go. The testing in |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4809.
Problem
D("lbl.com")with{label: "test", initialDomain: "ex.onmicrosoft.com", skypeForBusiness: true, mdm: true}produces:Only the MX moved. The token is
lbl-com, nottest-lbl-com.sipdir.online.lync.comandwebdir.online.lync.comno longer resolve.Root cause
if ((value.label = "@"))inhelpers.jsassigns instead of comparing, so the label is overwritten on every call anddomainGUIDis derived from the first argument alone. The Skype for Business and device management targets are the ones Microsoft published when the builder was written. The options object is also modified in place, so one object shared betweenD()blocks gives every later domain the first domain's MX and DKIM targets.Fix
Rewritten in Go against Microsoft's current documentation.
mxPriority,verificationToken,mxTarget,autodiscoverTarget,dkimSelector1Target,dkimSelector2Target,sipFederationTarget,mdmEnrollmentTarget,mdmRegistrationTarget.m365Options()passes the options object as an argument instead of throughrecord.metas, because the metadata path formats values with%s.M365_BUILDER()returns its modifier in an array, so theM365_BUILDER(...).concat()form keeps working.models/builders.goandRecordBuilderFnare unchanged.Behavior changes
Of the 27 calls I ran through both versions, 7 produce byte-identical records, 5 fail in both, and 15 change. The migration table in
M365_BUILDER.mdlists every one. The changes that break a working config:labelapplies to every record, not only to the MX.lyncdiscover,sipand_sip._tlsare gone,_sipfederationtls._tcpstays.mdmusesenterpriseenrollment-s.manage.microsoft.com.;mdmEnrollmentTargetrestores the old value.domainGUID.Tests
models/b_m365_test.go: table-driven, the record cases and every error with its exact wording, plus one options object shared between two domains.pkg/js/parse_tests/068-m365builder.js: apex,label,D_EXTEND(), the DKIM targets Microsoft assigns to domains created since May 2025, DANE, and aTTL()on the call.pkg/js/js_test.go: the error cases, including a record modifier passed to the call.M365_BUILDER.mdis rewritten, andcookbook.mddocumented ametadataparameter thatRecordBuilderFndoes not have and a helper that does not exist (mustbe.TagetHostWithSubdoman). Both corrected.Not in this PR
models.mergeMetasformats values with%s, which destroys booleans and numbers on the metadata path.mustbe.Uint16validates anint16without returning it.BuilderLOCdoes not setRecordConfig.SubDomain, and has no unit test.models.ImportRawRecordswraps every other branch withat %sbut returns the builder error unchanged.