Domain Registry Testing Guide
Documentation for Testing
Domain Registry — Internal Testing Guide
Feature: Subdomain Registry, Custom Domain Verification, Space-Branded Routing
Sessions: S234.4, S235.1
Branch: session-234-235
Prerequisites
- Backend running:
yarn serve:backend(port 3000) - Frontend running:
yarn serve:space(port 6200) - MongoDB running locally (or connected to dev environment)
- A space with at least 2 universes created
Test 1: Subdomain Availability Check (Launch Dashboard)
Navigate to: http://localhost:6200/space/{your-space-slug}/launch-station/dashboard
Steps
- Select a universe from the carousel
- Find the subdomain input field (has
.gograb.spacesuffix) - Type a subdomain name (e.g.,
my-test-site) - Wait ~500ms for the debounced check
Expected
| Input | Result |
|---|---|
my-test-site (unclaimed) |
Green "Available" indicator appears |
api |
Red "Taken" indicator (reserved name) |
admin |
Red "Taken" indicator (reserved name) |
app |
Red "Taken" indicator (reserved name) |
| Any already-deployed subdomain | Red "Taken" + suggestion chips appear below |
MY-SITE (uppercase) |
Input should be rejected by format validation |
a (too short) |
No check triggered (min 3 chars) |
What to verify
- Availability indicator shows "Checking..." spinner while request is in-flight
- Green checkmark for available subdomains
- Red X for taken/reserved subdomains
- Suggestion chips appear when subdomain is taken (clickable — clicking populates the input)
- Preview URL updates in real-time:
https://{subdomain}.gograb.space
Test 2: "Use My Own Domain" Toggle (Launch Dashboard)
Same page: Launch Dashboard
Steps
- Find the "I'll use my own domain" checkbox toggle
- Enable it
Expected
- Subdomain input disappears
- Custom domain input appears (placeholder:
app.mybrand.com) - Preview URL changes to show the custom domain (e.g.,
https://app.mybrand.com) - DNS info hint appears: "Point your domain's CNAME to gograb.space"
- Disable the toggle
Expected
- Custom domain input disappears
- Subdomain input reappears
- Preview URL reverts to
https://{subdomain}.gograb.space
Test 3: Subdomain Preview During Universe Creation
Navigate to: http://localhost:6200/space/{your-space-slug}/universe/create
Steps
- Start the universe creation wizard
- In Step 1 (Basic Info), type a universe name (e.g., "My Portal")
- Observe the area below the name input
Expected
- A preview line appears: "Platform URL: my-portal.gograb.space"
- Availability status shows next to the URL:
- "checking..." while verifying
- "available" with green checkmark if unclaimed
- "taken — you can change this later" with red X if claimed
- The slug updates automatically as you type the name
- Preview disappears if name is cleared
Important
This check is informational only — it does NOT block universe creation. The subdomain is claimed at deploy time.
Test 4: Space Info — Deployment Mode & Active Subdomains
Navigate to: http://localhost:6200/space/{your-space-slug}/dashboard
Steps
- Look at the Space Info panel (usually sidebar or top section)
- Check for deployment mode and subdomains section
Expected
- Deploy Mode badge shows
independent_subdomains(default) orspace_branded - Active Subdomains section lists all deployed universes with:
- Globe icon +
{subdomain}.gograb.spacefor each - Custom domain shown if set (e.g.,
app.mybrand.com)
- Globe icon +
- If no universes are deployed, the subdomains section does not appear
Test 5: Universe Settings — View & Edit Subdomain
Navigate to: Universe Hub for any deployed universe, then open Settings
Steps
- Open a universe's settings modal (gear icon or "Settings" button)
- Look for the "Deployed At" section
Expected (View Mode)
- Shows current subdomain:
{subdomain}.gograb.space - Shows custom domain if set
- "Change Subdomain" button is visible
Steps (Edit Mode)
- Click "Change Subdomain"
- An input field appears with
.gograb.spacesuffix - Type a new subdomain
- Click "Save Subdomain"
Expected
- If new subdomain is available: success toast, subdomain updates
- If new subdomain is taken: error toast with suggestions
- If new subdomain is reserved: error toast
- "Cancel" button reverts to view mode without changes
- The old subdomain is released and the new one is claimed atomically
Test 6: Deployment Modal — Correct URL Display
Trigger: Deploy a universe via the Launch Dashboard
Steps
- Go to Launch Dashboard
- Select a universe, enter a subdomain, click Deploy
- Wait for deployment to complete
- The success modal appears
Expected (Standard Deploy)
- Public URL shows:
https://{subdomain}.gograb.space - Cloud Preview shows the CF Pages URL (e.g.,
https://{project}.pages.dev) - Copy button works for the URL
Expected (Custom Domain Deploy)
- Enable "I'll use my own domain" before deploying
- Custom Domain section shows:
https://app.mybrand.com - Labeled as "Custom Domain" (not "Public URL")
Test 7: Dashboard Universe Cards — Deployed URLs
Navigate to: http://localhost:6200/space/{your-space-slug}/dashboard
Steps
- Look at the universe cards grid
Expected
- Each universe card shows a link icon with the deployed URL
- Deployed universes show:
{subdomain}.gograb.space(from the registry) - Undeployed universes show fallback:
gograb.space/{slug} - Deployed status badge shows correctly (Deployed / Draft)
Test 8: Deployment History — Subdomain & Domain Display
Navigate to: http://localhost:6200/space/{your-space-slug}/launch-station/history
Steps
- View the deployment history list
- Check each deployment card
Expected
- Each deployment entry shows:
- Version, environment badge, status
- Subdomain:
{subdomain}.gograb.space(globe icon) - Custom Domain:
{customDomain}(link icon, if applicable) - Timestamp, duration, user
- Environment filter works (All / Development / Staging / Production)
- Status filter works (All / Success / Failed / In Progress)
Test 9: Reserved Subdomain Protection
Via API or Launch Dashboard
Steps
Test that ALL of these subdomains are blocked:
| Category | Names |
|---|---|
| Platform infra | api, ai-api, docs-api, vitto-api, app, admin, dev, ai, docs, pulse, space-admin, vitto-updater |
| Common names | www, mail, ftp, ssh, ns1, ns2, staging, preview, test, demo, dashboard, console, portal, login, status, health, cdn, assets, static |
Via API (quick check)
curl "http://localhost:3000/api/deployed-subdomains/check?subdomain=api"
# Expected: {"available":false}
curl "http://localhost:3000/api/deployed-subdomains/check?subdomain=my-unique-name-12345"
# Expected: {"available":true}
Via UI
Type any reserved name in the Launch Dashboard subdomain input — should show "Taken".
Test 10: Subdomain Suggestions
Via API or Launch Dashboard
Via API
curl "http://localhost:3000/api/deployed-subdomains/suggest?spaceSlug=my-space&universeSlug=portal"
# Expected: {"suggestions":["portal","portal-my-space","my-space","my-portal","portal-app","portal-xxxx"],"requested":"portal"}
Via UI
- In Launch Dashboard, enter a taken subdomain
- Suggestion chips should appear below the input
- Click a suggestion — it should populate the input and re-check availability
Test 11: Custom Domain Verification Flow
Via API (DNS verification requires actual domain ownership)
Step 1: Initiate verification
curl -X POST "http://localhost:3000/api/deployed-subdomains/universe/{universeId}/verify-domain/initiate" \
-H "Content-Type: application/json" \
-d '{"customDomain": "app.example.com"}'
Expected response:
{
"txtRecordName": "_gograb-verify.app.example.com",
"txtRecordValue": "gograb-verify=abc123...",
"instructions": "Add a TXT record to your DNS:..."
}
Step 2: Check status
curl "http://localhost:3000/api/deployed-subdomains/universe/{universeId}/verify-domain/status"
Expected: Shows verification state (pending, with TXT record details).
Step 3: Attempt verification
curl -X POST "http://localhost:3000/api/deployed-subdomains/universe/{universeId}/verify-domain/check"
Expected (without actual DNS record): {"verified": false, "error": "DNS lookup failed: ENOTFOUND..."}
Test 12: Collision Prevention (Critical)
Test A: Same subdomain, different universes
- Deploy Universe A with subdomain
test-collision - Try to deploy Universe B with the same subdomain
test-collision
Expected: Universe B's deployment fails with ConflictException: Subdomain "test-collision.gograb.space" is not available (taken)
Test B: Idempotent re-deploy
- Deploy Universe A with subdomain
test-idem - Re-deploy Universe A with the same subdomain
test-idem
Expected: Succeeds — same universe re-claiming its own subdomain is idempotent.
Test C: Release on undeploy
- Deploy Universe A with subdomain
test-release - Undeploy Universe A
- Check availability of
test-release
Expected: Available again.
- Deploy Universe B with subdomain
test-release
Expected: Succeeds — released subdomains can be re-claimed.
Test 13: E2E Automated Tests
Run the automated test suite:
cd tests/platform-creation-e2e
npx jest src/tests/api/domain-registry.spec.ts --verbose
Expected: 35+ tests pass across 9 test suites:
- Subdomain availability check (9 tests)
- Subdomain suggestions (5 tests)
- Subdomain claiming (5 tests)
- Space lookup (3 tests)
- Universe lookup (3 tests)
- Subdomain update (6 tests)
- Custom domain verification (5 tests)
- Reserved subdomains (1 parameterized test, 23 names)
- Space routes (2 tests)
API Quick Reference
All endpoints are at http://localhost:3000/api/deployed-subdomains/...
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /check?subdomain=X&environment=production |
No | Check availability |
| GET | /suggest?spaceSlug=X&universeSlug=Y |
No | Get suggestions |
| GET | /space/:spaceId |
No | List space subdomains |
| GET | /universe/:universeId |
No | Get universe subdomain |
| GET | /space-routes/:spaceSlug |
No | Get CF Worker routing table |
| PATCH | /universe/:universeId |
Yes | Update subdomain/domain |
| POST | /universe/:id/verify-domain/initiate |
Yes | Start verification |
| POST | /universe/:id/verify-domain/check |
Yes | Check DNS record |
| GET | /universe/:id/verify-domain/status |
No | Get verification status |
Known Limitations
- Custom domain verification requires actual DNS access — can only be fully tested with a real domain
- Space-branded path routing (CF Worker) is coded but not deployed — requires KV namespace setup on Cloudflare
- Deployment History currently uses mock data for display — real history comes from the backend
deploymentscollection - Subdomain suggestions include a random 4-char suffix as a last resort — results vary per call