DEV Community

MaximilianNilsson7568
MaximilianNilsson7568

Posted on

5 Domain Verification and Email Confirmation Rules for Workspace Joining Control

Short answer: treat mailbox confirmation and DNS verification as two different evidence records, then require an explicit policy transition before a person joins a property-management workspace. Mail proves control of one inbox at a moment in time. DNS proves that someone can change an authoritative zone. Neither fact, alone, proves that a particular employee should receive a role containing tenant or maintenance data.

That distinction is the useful architecture. A leasing company may have a central DNS administrator, local property managers, contractors, and shared reception mailboxes. If those identities collapse into one verified flag, the system cannot explain who crossed an organisational boundary or revoke the right evidence later.

How should domain verification and email confirmation govern workspace joining?

The first design decision is to name the assertion, not the feature. An email challenge establishes “this person completed a challenge delivered to this mailbox.” A DNS token establishes “someone who can publish this value in the domain’s authoritative zone did so.” An invitation establishes “an authorised workflow selected this user for this workspace.” Those are separate statements with separate failure modes.

I initially treated “verified domain” as a durable user attribute. That was the wrong boundary: a DNS observation belongs to a claim, has an age, and can be revoked independently of a person.

I store them as separate events. A domain claim has a normalised name, a random token, the expected record name and type, the resolver observation, and timestamps. A mailbox confirmation has a user identifier, challenge expiry, delivery target, and completion time. An invitation records the workspace, actor, requested role, and decision. The schema is slightly more tedious, but an incident review can then distinguish a stale TXT record from an unauthorised role grant.

Evidence Strong assertion Appropriate consequence Boundary to preserve
Mailbox challenge One person controls one mailbox now Verify a join request or complete an invitation Forwarding, aliases, shared inboxes, departed staff
DNS token Someone controls publication in the zone Mark a domain eligible for an organisational policy Delegation, stale records, registrar compromise
Explicit invitation An authorised workflow selected this person Assign a named role in one workspace Misapproval or excessive scope

The distinction matters more than the user interface. A green checkmark is not an authority model.

How should the join path handle a shared domain?

For a property-management customer, domain eligibility can narrow the set of acceptable email domains, while an invitation or approval supplies the final decision. The policy might allow manager@leasing.example to request access to the “North Region” workspace, but it should still evaluate the invitation, the requested role, and any organisation-specific approval rule before granting access to tenant records.

The critical path is intentionally boring:

from dataclasses import dataclass
from datetime import datetime

@dataclass
class DomainClaim:
    name: str
    token: str
    verified_at: datetime | None = None
    revoked_at: datetime | None = None

def observe_dns(claim: DomainClaim, txt_values: list[str], now: datetime) -> bool:
    if claim.revoked_at is not None:
        return False
    if claim.token not in txt_values:
        return False
    claim.verified_at = now
    return True

def may_join(email: str, claim: DomainClaim, invited: bool) -> bool:
    if not invited or claim.verified_at is None or claim.revoked_at is not None:
        return False
    _, domain = email.rsplit("@", 1)
    return domain.casefold() == claim.name.casefold()
Enter fullscreen mode Exit fullscreen mode

This function only supplies evidence for a policy decision. It does not assign an administrator role, and it does not treat a cached observation as permanent. A production policy should also check invitation state, workspace identity, role scope, and the age of the observation.

DNS caching is the awkward part. Recursive resolvers can retain a response until its TTL expires, and authoritative data can change while a verifier still sees the previous value. A positive observation therefore needs a timestamp and a re-verification rule; it should not be copied forever into a user row. In a 2026 deployment, the resolver response, observed record, timestamp, and token version should travel together in the audit event so an operator can tell a fresh answer from a cached one; retaining only a boolean loses the exact evidence at the moment a role was granted. The exact interval is an organisational policy choice. The protocol does not choose it for you.

Email has a different awkward part. A shared office@ address can satisfy a challenge even though several people can read it, while forwarding can continue after an employee leaves. A mailbox event is useful for person-level confirmation, but it is weak evidence for an organisation-wide claim. Treating it as a domain claim is a shortcut with an invisible blast radius.

Which failure boundaries deserve tests?

Negative tests reveal whether the model is real. Exercise an expired challenge, an old token, a TXT value at the wrong host, a case-variant domain, a revoked invitation, and a claim moved from one workspace to another. Also test a delegated subdomain: control of south.leasing.example should not silently establish control of leasing.example.

The verifier should compare the exact expected record type and name, and it should record the resolver view used for the observation. Logging only “verification succeeded” throws away the evidence needed to investigate a registrar compromise or a forgotten record. Keep token creation, DNS observation, invitation approval, and role assignment as separate audit events.

Names drift. That is enough reason to test the negative path first.

I rejected the tempting flow “confirm any mailbox, then claim its domain.” It is acceptable for a low-risk personal workspace where the domain is merely a convenience label. It is not a sound boundary for tenant data, because the proof changes from a person-level event to an organisation-level authority without a new actor or approval step.

The reverse mistake also occurs: requiring DNS control for every join. A small office may have no DNS operator available, and a contractor may need a narrowly scoped invitation. In that case, invitation-only access is a coherent policy, provided the organisation accepts the weaker automation and keeps the approval evidence. Architecture is a set of explicit trade-offs, not a contest to maximise verification steps.

What does email authentication contribute?

DMARC is useful adjacent evidence, not a membership protocol. RFC 7489 defines domain alignment and reporting for email authentication; it does not establish that a particular employee belongs in a workspace. SPF, DKIM, and DMARC signals can help an operator understand mail provenance, but they should not be substituted for a domain claim or an invitation decision.

Operationally, alert on repeated failed observations, claims with no recent successful observation, and role grants that lack a matching invitation event. During an incident, an operator should be able to answer three questions quickly: who changed DNS, who approved the join, and which role was granted? If the data model cannot answer them independently, the join flow is hiding authority inside an authentication check.

Keep revocation explicit. A removed TXT record should stop future verification, but it cannot erase an already granted role by magic; the policy must define whether a claim is rechecked, suspended, or reviewed. Likewise, deleting a mailbox does not prove that every existing session or invitation is invalid. Those are lifecycle decisions, and they belong in the access policy and runbook.

For property-management teams, the durable rule is simple: mailbox confirmation identifies a person, DNS verification identifies a domain operator, and an explicit policy transition grants workspace access. The three records make different promises. Preserve those boundaries and the system can explain its decisions without pretending that one challenge proves every kind of ownership.

References

Top comments (0)