Outcome
Change the local form routing association of an owned domain without transferring its ownership or reproving DNS.
PATCH /api/domains/{domainId}
Before you start
Use the original authorized organization and a discovered canonical Forms workspace, bound separately. List needs workspace:read; writes need workspace:write. Bearer requests resolve minimum read for list and admin for domain writes. API-key authority comes through original Auth introspection of its binding and the app permission check; do not invent an additional local role check.
Only connect a hostname and DNS zone you are authorized to administer. Organization visibility does not transfer ownership or mutation authority. The projection does not identify its owning workspace. An ownership TXT token is not an Auth credential or platform grant.
These actions return planned DNS instructions; they do not publish DNS records. Preserve unrelated mail/TXT records during any separately approved DNS administration. Syntax validity is not global hostname registry custody, reserved-hostname enforcement, exclusive ownership or correct provider origin. Those surrounding contracts remain with their existing owners.
All examples are complete source-derived synthetic responses, unrun. Names, ids, ownership token and example.test URLs are fictional. The exact published domain-connections0.4.4 artifact matches the checked lock integrity and was inspected without import/execution. No real DNS lookup/write, Cloudflare, form/subject/Auth/provider/model/notification operation or browser navigation occurred.
Request and effects
Action: app_topolo_forms.domains.assign. Validate current input and, for a real mutation, obtain applicable approval and a confirmed executable plan for the exact owner-scoped target and provider/public effects.
Requires domainId,target formId and original owner-workspace mutation authority. Organization visibility does not permit another workspace to repoint it; non-owned rows return404 domain_not_found.
Target form must exist in the same original organization/selected workspace or404 form_not_found. Published status is not required by this lookup, so assignment to a draft does not make the target publicly ready.
The update sets form_id,workspace_id,updated_at, then reads back separately. Prior ownership validation makes this a same-owner reassignment, not a supported cross-workspace transfer. Hostname,target,token,availability and status otherwise remain.
There is no DNS/provider operation in this branch. An active public-domain resolver uses the local form association, while actual edge propagation and target publication are separate. No expected-version/CAS transaction protects the read-check-update; reconcile later owner changes before repeating or compensating.
Complete worked responses
Association changed
Complete source-derived synthetic, unrun HTTP200. Assumes the fictional active row is owned here, target form exists here and update/read-back succeeds at the shown clock. No DNS/provider/public request.
Input:
{
"domainId": "domain_00000000-0000-4000-8000-000000000004",
"formId": "forms_other_docs_fixture"
}
Response:
{
"domain": {
"id": "domain_00000000-0000-4000-8000-000000000004",
"hostname": "forms.example.test",
"status": "active",
"verificationToken": "00000000-0000-4000-8000-000000000003",
"dnsTarget": "edge.example.test",
"formId": "forms_other_docs_fixture",
"availableAcrossWorkspaces": false,
"records": [
{
"purpose": "routing",
"type": "CNAME",
"host": "forms",
"name": "forms.example.test",
"value": "edge.example.test",
"required": true,
"instruction": "Publish a CNAME from forms to edge.example.test. Leave MX, SPF, and DKIM records unchanged."
},
{
"purpose": "ownership",
"type": "TXT",
"host": "_topolo-verification.forms",
"name": "_topolo-verification.forms.example.test",
"value": "topolo-verification=00000000-0000-4000-8000-000000000003",
"required": true,
"instruction": "Publish a TXT record at _topolo-verification.forms.example.test with this exact value. Leave every other TXT record unchanged."
}
],
"createdAt": "2026-10-21T01:00:00.000Z",
"updatedAt": "2026-10-21T01:05:00.000Z"
}
}
Preserve actual original target/request evidence and follow verification/recovery; the fixture authorizes no operation.
Target form absent
Complete source-derived synthetic, unrun HTTP404. Assumes domain ownership passes but target form is absent; no association update.
Input:
{
"domainId": "domain_00000000-0000-4000-8000-000000000004",
"formId": "forms_absent_docs_fixture"
}
Response:
{
"error": "form_not_found"
}
Preserve actual original target/request evidence and follow verification/recovery; the fixture authorizes no operation.
Domain not owned here
Complete source-derived synthetic, unrun HTTP404. Assumes the row is visible across the organization but not owned by selected workspace; no transfer permission follows.
Input:
{
"domainId": "domain_00000000-0000-4000-8000-000000000004",
"formId": "forms_docs_fixture"
}
Response:
{
"error": "domain_not_found"
}
Preserve actual original target/request evidence and follow verification/recovery; the fixture authorizes no operation.
Verify and recover
-
Read domains.list and compare exact id/new formId in the original context, retaining the reviewed prior association. Verify required target publication/public behavior separately.
-
Reconcile current owner/association before repeat or compensation; visibility and stored status do not establish target readiness or transfer authority.
After current-state reconciliation and separate approval, plan restoration to the verified prior same-owner form. This is a new update/timestamp, not reversal of public accesses or submissions.
Refusals and uncertainty
400 / workspace_required: Discover/bind the original authorized canonical workspace through Auth; input is not a grant.
403 / forbidden: Preserve actual permission denial and use its owner for legitimate access.
404 / domain_not_found: Reconcile discovered domain and owner workspace; organization visibility is not mutation authority.
422 / invalid_hostname: Use the actual legitimate plain hostname/plan, without bypassing policy or publishing fictional records.
404 / form_not_found: Discover an actual form in the same owner workspace; do not repoint another workspace to force a match.
Concrete branches differ from shared runtime failures. DNS,provider,local state and read-back can disagree after interrupted work; a response is not a complete external effect or rollback receipt.
Related actions
Change log
- 2026-10-21: Added owner-workspace/organization visibility, exact published DNS plans, provider/local sequencing, complete illustrative responses and scoped recovery. All examples remain synthetic and unrun.