User guide
Domains
Looking for what it does rather than how to use it? Read the Domain Management overview .
The Domains section gives an organization — and the MSP that manages it — one place for every domain name it depends on: registered (public) domains held at any registrar, the internal Active Directory / Entra / private-DNS domains a network answers to, and domains bought through Tridacom’s own registrar channel.
Where: /msp/domains (across managed clients) and /org/domains. Platform configuration for the Tridacom channel lives at /platform/integrations/domain-registrar.
What a domain row knows
| Area | Facts | Source |
|---|---|---|
| Registration | registrar of record, registered / expires / last-changed dates, auto-renew, transfer lock, WHOIS privacy, DNSSEC, EPP statuses, nameservers, registrant | registrar sync, Tridacom, or public RDAP |
| Hosting | where DNS is served and where mail is hosted, inferred from NS and MX | live DNS probe |
| Email security | SPF (record, lookup count, all qualifier), DMARC (policy, reporting, pct), DKIM selectors found, CAA | live DNS probe |
| Certificate | issuer, expiry, name match, chain trust on the apex or www | TLS probe |
| Health | 0–100 score with findings (EXPIRES_7D, NO_TRANSFER_LOCK, SPF_MISSING, DMARC_WEAK, TLS_EXPIRED, …) and a hint per finding | probe |
| Business | owner, technical contact, criticality, purpose, renewal cost, reminder thresholds, contract, site, tags, notes, linked assets | people |
| History | every change to a tracked fact or DNS record (what, when, which source), every probe run | probe / syncs / users |
Registry facts are never editable on a synced row — the provider is the authority and a hand edit would be undone within the hour. Business fields are never touched by any sync.
Three ways a domain arrives
- Add by hand (
Add domain, or bulk import). Registry facts come from public RDAP (bootstrapped from IANA, per-TLD authoritative server, one hop to the registrar’s RDAP when linked) and the live DNS/TLS probe. No credentials needed. - Connect a registrar (
Registrar connections): GoDaddy, Cloudflare, Namecheap. Read-only; every six hours (or on demand) the account’s domains are imported with expiry/lock/auto-renew/nameservers and hosted zones are snapshotted. On the MSP portal each domain in a shared account is placed on the client organization that owns it; placement moves the row immediately. A domain that vanishes from the account is marked Transferred out, never deleted. - Register or transfer through Tridacom (
Register or transfer): search availability and price, register or bring a domain in with its EPP code, then manage nameservers, hosted DNS, lock, privacy, auto-renew, contacts and renewals from the same detail page.
Tridacom domain services (distribution partner distribution partner)
Tridacom is the distribution partner reseller; one platform-level account serves every tenant.
Pricing has three layers, frozen on every order:
- wholesale (distribution partner) — visible only to platform admins
- MSP price — what an MSP account pays Tridacom (per-TLD list, or wholesale + default markup)
- customer price — the MSP price plus the MSP’s own markup (percent + optional
.99rounding; never below the MSP price), or the retail price for an organization with no MSP
Transfers bill only when the registry completes them. Auto-renew domains are renewed by the nightly job autoRenewLeadDays (default 30) before expiry and billed to the account that placed the last order; distribution partner’s own auto-renew stays on as a safety net and, if it fires, the registrar event raises the renewal order retroactively so the customer is billed exactly once.
Currency. distribution partner bills the reseller in one currency (Tridacom’s account is billed in USD) and Tridacom sells in another (CAD). The account tab carries both — Selling currency (what every price-list figure and every invoice is denominated in) and Currency distribution partner bills us in — plus an FX spread added to the mid-market rate, because the bank does not settle at the ECB mid. Pulling wholesale converts before it stores, using the FxRate table, and refuses outright if no rate is available rather than recording a USD figure as CAD. Nothing used to convert: a US$14.50 .com was stored as 1450 and marked up 20% to 1740 against a real cost of C$20.01, so the margin was negative and the never-sell-below-cost floor could not see it. Change the selling currency and re-run refresh costs to restate the list.
Platform admin (/platform/integrations/domain-registrar): reseller username/API key (encrypted at rest, never returned), test/live environment, default nameservers, Tridacom’s technical contact, default markups, the TLD price list (pull wholesale from distribution partner, edit MSP/retail — the list refuses to sell below cost), the order ledger with margins, and the registrar event feed.
MSP reseller terms (bottom of Registrar connections): markup percent, rounding, default auto-renew / privacy / lock, and whether managed clients may order themselves (billed to the MSP, re-billed at the MSP’s price).
An un-allow-listed caller gets
400 Access denied: invalid ip address— the key is fine, the source address is not, and it is the NAT/egress address that must be listed.
Renewals and notifications
- Domain expiry and TLS certificate expiry appear on the Renewals workspace (
/software/renewals) asDomainandCertificaterows on the shared window. - Daily job
domain-expiry-notificationssendsDOMAIN_EXPIRINGat each domain’s reminder thresholds (default 60/30/14/7/1 days, editable per domain),DOMAIN_HEALTH_ISSUEfor certificates at 14/3 days and for health under 50 (deduped for 7 days). Recipients: the organization’s admins/managers/technicians plus the domain’s business owner.
Jobs
| Job | Schedule | Does |
|---|---|---|
domain-expiry-notifications | 07:15 UTC | reminders and health notices |
domain-registrar-events | every 10 min | drains the distribution partner event queue, re-applies stored events that failed, reconciles pending orders |
registrar-portfolio-sync | 05:30 UTC | reconciles the domains and certificates the distribution partner account holds against the placement list |
The reseller portfolio: what the account holds vs. who owns it
Tridacom’s distribution partner account is one account for the whole platform, so a name in it is not automatically anybody’s. ManagedDomain.organizationId is required, so until this existed a domain bought directly in the distribution partner control panel — or one predating Solidlio — had nowhere to live and did not appear in the product at all.
RegistrarPortfolioDomain (and RegistrarPortfolioCertificate for SSL) is the waiting room. registrar-portfolio-sync (05:30 UTC daily) lists the holdings — GET_DOMAINS_BY_EXPIREDATE for domains, GET_PRODUCTS for certificates, both keyed on an expiry window because neither has an “everything we own” call — and /platform/integrations/domain-registrar → Portfolio is where a platform admin assigns each one to an organization.
Nothing is auto-assigned by name. A domain name is not evidence of who owns it, and ManagedDomain is unique on organizationId+name rather than on name, so two tenants can legitimately track the same one. Auto-linking runs only where the evidence is unambiguous: exactly one existing row, and for certificates the distribution partner product id, which identifies one certificate rather than a string two tenants might share.
Placement adopts an existing row rather than failing on the unique constraint (the customer may have added the domain by hand, and that row carries their tags, criticality and asset links), then refreshes it from the registrar. Placing a certificate downloads it with get_cert and files it through the same ingestCertificate path an order uses, carrying tridacomProductId so renewal and reconciliation attach to it. The private key is not part of that and cannot be — distribution partner never had it — so the row lands keyLocation: EXTERNAL.
A holding that disappears from the provider is flagged missingSince, never deleted: it may still be billed, and the row carries the placement decision.
The whole surface is platform administrator, including the organization picker. That is a tenancy rule, not a convenience one: the list spans every customer of the reseller account, so exposing it to an MSP would show that MSP unrelated tenants’ domain names. An MSP sees a name only once it is placed on one of its own organizations, through the ordinary scoped routes.
distribution partner event notifications: poll and webhook
distribution partner delivers the same events two ways and the control panel (Account Settings → Event notifications) toggles them per event type. Both are on.
- Poll is the guarantee. Nothing leaves the queue until we acknowledge it, so an event cannot be lost by a bad deploy or a rotated secret.
- Webhook is the latency.
Response codes decide whether an event survives, so the receiver picks them deliberately: a 2xx is never resent, a 3xx/4xx is dropped permanently, and only a 5xx is retried (backoff, five attempts over 24 hours). An unverifiable body gets 401 (forged, or signed with a secret we no longer hold — resending would not help), a receiver with no secret configured yet gets 503 (24 hours to paste it in), and a signed body we cannot interpret gets 202 and a log line rather than five identical redeliveries.
The shared secret is set in the platform admin page. distribution partner regenerates it every time the webhook URL changes, so a URL edit without re-pasting the secret makes every push fail verification — silently, because a rejected push is a 4xx and is dropped. That is the second reason poll stays on.
The two channels carry different ids for the same change (the queue’s is a counter, the webhook’s a UUID), so an event can arrive twice. Nothing dedupes across them; instead every handler is a no-op the second time — order and transfer lookups only match orders still open, an external renewal is skipped when a recent one is on file, and a domain refresh just re-reads the registry. DomainProviderEvent.deliveredBy records which channel a row came from.
Plan gating
Registrar connections gate as one capability, domain_management (in the integrations allowlist of every seeded tier, like secrets_management). Tridacom orders are gated by the platform kill switches, not by tier.