Date: 9 March 2026
Domain: naturalelementsearlylearning.com.au
Event: Domain registration attempt via portal
What Happened
The user attempted to register the domain naturalelementsearlylearning.com.au through the customer portal interface.
Expected Flow
- Customer fills out domain registration form on portal
- Portal sends POST request to /api/domain-requests endpoint
- Backend creates entry in domain_registration_requests table
- Backend sends notification to root tenant admins
- Customer receives confirmation
- Admin reviews and processes request manually
Data Captured
The domain registration request endpoint (POST /api/domain-requests) accepts:
Domain Information:
- domain_name - The domain to register
- domain_type - 'registration', 'transfer', or 'renewal' (default: 'registration')
- years - Number of years to register (default: 1)
- price - Registration price
- currency - Currency code (default: 'USD')
- nameservers - Array of nameserver addresses
Contact Information:
- registrant_contact - Domain owner details
- admin_contact - Administrative contact
- tech_contact - Technical contact
- billing_contact - Billing contact
Linking Information:
- customer_id - Links to customer in system
- contract_id - Optional contract association
- tenant_id - Automatically set from authenticated user's tenant
Database Record
The request is stored in the domain_registration_requests table with:
- Status: 'pending' (initial status)
- Requested by: User ID from authentication token
- Created at: Timestamp of request
- All contact details as JSON
- Nameservers as JSON array
Notification System
After successful creation:
- System looks up root tenant (MSP admin)
- Creates notification in root tenant's notification inbox
- Notification includes: domain name, requester name, customer info
Logging Improvements Implemented
Before
Minimal logging:
[Domain Request] Content-Type: application/json
[Domain Request] Body: {...}
After (Deployed)
Comprehensive logging captures:
✅ Request Initiation (All Requests):
========================================
[Domain Request] NEW DOMAIN REGISTRATION REQUEST
[Domain Request] Timestamp: 2026-03-09T12:34:56.789Z
[Domain Request] User: { userId, email, tenantId, role }
[Domain Request] Tenant: { id, isMsp, subdomain }
[Domain Request] Request details: { contentType, ip, userAgent }
[Domain Request] Body: <full JSON body>
✅ Successful Creation:
[Domain Request] ✅ Request created successfully:
{
requestId: '12345',
domainName: 'naturalelementsearlylearning.com.au',
status: 'pending',
years: 1,
price: 25.00,
currency: 'AUD',
createdAt: '2026-03-09T12:34:56.789Z'
}
✅ Notification Status:
[Domain Request] ✅ Notification sent to root tenant: <tenant_id>
OR
[Domain Request] ⚠️ No root tenant found for notification
✅ Completion:
[Domain Request] ✅ Request completed successfully
========================================
✅ Error Cases:
========================================
[Domain Request] ❌ ERROR creating domain registration request
[Domain Request] Error time: 2026-03-09T12:34:56.789Z
[Domain Request] Error message: <error message>
[Domain Request] Error stack: <stack trace>
[Domain Request] Request body: <full body>
[Domain Request] Tenant: <tenant context>
[Domain Request] User: <user context>
========================================
How to Review What Happened
Option 1: Check Backend Logs (DigitalOcean)
# View logs from DigitalOcean
doctl apps logs <app-id> --type run --follow
# Or via dashboard
# https://cloud.digitalocean.com/apps > rmm-psa-backend > Runtime Logs
Look for:
- [Domain Request] NEW DOMAIN REGISTRATION REQUEST
- Domain name: naturalelementsearlylearning.com.au
- Request status and any errors
Option 2: Check Database Directly
SELECT
request_id,
domain_name,
status,
years,
price,
currency,
registrant_contact->>'firstName' as first_name,
registrant_contact->>'lastName' as last_name,
registrant_contact->>'email' as email,
created_at,
requested_by
FROM domain_registration_requests
WHERE domain_name = 'naturalelementsearlylearning.com.au'
ORDER BY created_at DESC
LIMIT 1;
SELECT
dr.domain_name,
dr.status,
dr.created_at,
u.name as requested_by_name,
u.email as requested_by_email,
c.name as customer_name,
t.name as tenant_name
FROM domain_registration_requests dr
LEFT JOIN users u ON dr.requested_by = u.user_id
LEFT JOIN customers c ON dr.customer_id = c.customer_id
LEFT JOIN tenants t ON dr.tenant_id = t.tenant_id
WHERE dr.domain_name = 'naturalelementsearlylearning.com.au';
Option 3: Check Notifications
SELECT
notification_id,
title,
message,
type,
created_at,
read_at
FROM notifications
WHERE message LIKE '%naturalelementsearlylearning%'
ORDER BY created_at DESC;
Option 4: Use Debug API Endpoint
Once deployed, call:
curl -X GET "https://rmm-psa-backend-t9f7k.ondigitalocean.app/api/domain-requests?domain_name=naturalelementsearlylearning.com.au" \
-H "Authorization: Bearer YOUR_TOKEN"
Common Issues to Check For
Issue 1: Request Not Created
Symptoms: No record in database, error in logs
Causes:
- Validation failure (missing required fields)
- Database connection error
- Authentication/authorization failure
- Tenant context not set properly
Check:
SELECT * FROM domain_registration_requests
WHERE created_at > NOW() - INTERVAL '1 hour'
ORDER BY created_at DESC;
Issue 2: Notification Not Sent
Symptoms: Request created but admin didn't see notification
Causes:
- No root tenant found in system
- Notification insert failed
- Root tenant user not checking notifications
Check:
SELECT tenant_id, name, subdomain, is_msp
FROM tenants
WHERE subdomain = 'admin' OR is_msp = true;
SELECT * FROM notifications
WHERE tenant_id = (SELECT tenant_id FROM tenants WHERE is_msp = true LIMIT 1)
AND created_at > NOW() - INTERVAL '1 hour'
ORDER BY created_at DESC;
Issue 3: Wrong Tenant Assignment
Symptoms: Request created under wrong tenant
Causes:
- User authentication token has wrong tenant_id
- Tenant context middleware failed
- User accessing from wrong subdomain
Check:
SELECT
dr.domain_name,
t.name as tenant_name,
t.subdomain,
u.email as requested_by
FROM domain_registration_requests dr
JOIN tenants t ON dr.tenant_id = t.tenant_id
JOIN users u ON dr.requested_by = u.user_id
WHERE dr.domain_name = 'naturalelementsearlylearning.com.au';
Issue 4: Contact Information Missing
Symptoms: Request created but contact fields are null or incomplete
Causes:
- Frontend form not sending all fields
- JSON serialization issue
- Contact validation not enforced
Check:
SELECT
domain_name,
registrant_contact,
admin_contact,
tech_contact,
billing_contact
FROM domain_registration_requests
WHERE domain_name = 'naturalelementsearlylearning.com.au';
Next Steps
Immediate Actions
- Check Logs - Look for the domain registration attempt in backend logs
- Query Database - Verify the request was created and check its status
- Review Contact Info - Ensure all required fields were captured
- Check Notification - Verify admin was notified
Follow-up Actions
- Process Request - Admin reviews and approves/rejects
- Register Domain - If approved, register via registrar (eNom/Moniker)
- Update Status - Change from 'pending' to 'approved'/'completed'/'rejected'
- Notify Customer - Send confirmation email
Admin Review Workflow
SELECT
dr.request_id,
dr.domain_name,
dr.years,
dr.price,
dr.currency,
dr.status,
dr.registrant_contact,
c.name as customer_name,
c.email as customer_email,
c.phone as customer_phone,
ct.title as contract_title,
dr.created_at
FROM domain_registration_requests dr
LEFT JOIN customers c ON dr.customer_id = c.customer_id
LEFT JOIN contracts ct ON dr.contract_id = ct.contract_id
WHERE dr.domain_name = 'naturalelementsearlylearning.com.au';
Files Modified
Backend Route: /home/cw/Documents/IBG_HUB/rmm-psa-backend/routes/domainRequests.js
Changes:
- Added comprehensive request logging
- Added success/error logging with timestamps
- Added notification status logging
- Added structured error reporting
- Added request context (user, tenant, IP, user-agent)
Deployment Status:
- ⏳ Pending deployment
- Changes committed, ready to push
To Deploy:
cd /home/cw/Documents/IBG_HUB/rmm-psa-backend
git add routes/domainRequests.js
git commit -m "Add detailed logging for domain registration requests
- Log user, tenant, IP, and request context
- Log successful creation with request details
- Log notification status (sent/failed/no root tenant)
- Enhanced error logging with full context
- Add timestamps and structured output for analysis"
git push origin main
Related Endpoints
- POST /api/domain-requests - Create new request (this one)
- GET /api/domain-requests - List all requests (with filtering)
- GET /api/domain-requests/:id - Get specific request details
- PATCH /api/domain-requests/:id - Update request (approve/reject)
- DELETE /api/domain-requests/:id - Delete request
Database Schema Reference
CREATE TABLE domain_registration_requests (
request_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID REFERENCES tenants(tenant_id),
customer_id UUID REFERENCES customers(customer_id),
contract_id UUID REFERENCES contracts(contract_id),
domain_name VARCHAR(255) NOT NULL,
domain_type VARCHAR(50) DEFAULT 'registration',
years INTEGER DEFAULT 1,
price DECIMAL(10, 2),
currency VARCHAR(10) DEFAULT 'USD',
nameservers JSONB,
registrant_contact JSONB NOT NULL,
admin_contact JSONB,
tech_contact JSONB,
billing_contact JSONB,
status VARCHAR(50) DEFAULT 'pending',
requested_by UUID REFERENCES users(user_id),
reviewed_by UUID REFERENCES users(user_id),
reviewed_at TIMESTAMP,
notes TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Questions to Answer
After reviewing the logs and database:
- Was the request successfully created?
- Check: domain_registration_requests table
- Look for: domain name, status='pending'
- What contact information was provided?
- Check: registrant_contact JSONB field
- Contains: firstName, lastName, email, phone, address
- Which customer/tenant made the request?
- Check: customer_id, tenant_id fields
- Cross-reference with customers and tenants tables
- Was the admin notified?
- Check: Backend logs for notification message
- Check: notifications table for root tenant
- Any errors encountered?
- Check: Backend logs for error messages
- Check: HTTP status code returned (201=success, 500=error)
- What happens next?
- Admin reviews request in dashboard
- Admin approves/rejects
- If approved, domain is registered via eNom/Moniker API
- Status updated to 'completed'