5.8 KiB
CHD Registration Domain Challenge (Concept)
1. Purpose
Document a future hardening design for CHD installation registration that:
- Keeps new cloud setup mostly automatic
- Reduces abuse of open registration (
/api/sovereign/v1/install/register) - Preserves backward compatibility with current connector behavior
This is a design note only (not implemented yet).
2. Problem
Current registration can be fully automatic, which is good for UX.
Risk:
- If registration is open (no registration token required), attackers can spam fake installations.
- CHD may create registry/customer records for domains the caller does not control.
- Abuse can pollute instance registry, create noise in support/admin tooling, and consume resources.
3. Goals
- Prove caller controls the claimed public cloud domain.
- Keep first-run setup simple for legitimate users.
- Support both:
- open registration mode (developer-friendly)
- token-required registration mode (hardened production)
- Allow phased rollout without breaking existing installs.
4. Non-goals (for this phase)
- Proving Qortal address ownership cryptographically
- Preventing all abuse without rate limits or moderation
- Replacing CHD registration tokens entirely
Qortal ownership proof can be added later as a higher-trust layer (for grants/high-risk actions).
5. Proposed model
Use a two-step registration state:
registered_unverifieddomain_verified
Optional later:
qortal_verifiedbilling_active
Registration may remain automatic, but higher-risk actions can require stronger state.
6. Domain challenge flow (proposed)
6.1 Step A: Initial registration request
Cloud calls:
POST /api/sovereign/v1/install/register
Payload includes (as it does today):
instanceId(optional client-supplied hint)nextcloudPublicUrladminEmail(optional)adminQortalAddress(optional but recommended/used)- mode/provider metadata
CHD response returns:
- normal instance credentials (
instanceId,instanceToken,instanceSecret) - registration state =
registered_unverified - a domain challenge object, e.g.:
challengeIdchallengeTokenexpiresAtverifyPath(suggested URL path to expose)
6.2 Step B: Cloud proves domain control
Cloud exposes challenge token at a deterministic public URL under the claimed domain.
Examples:
https://<cloud-domain>/.well-known/sovereign-chd/<instanceId>https://<cloud-domain>/apps/qortal_integration/api/chd/verify
CHD verifies by fetching that URL over HTTPS and matching the challenge token.
6.3 Step C: Verification result
If valid:
- CHD marks instance
domain_verified - CHD allows checkout issuance (recommended)
- CHD can elevate trust for later automation flows
If invalid/expired:
- instance remains
registered_unverified - CHD may allow only limited operations or block checkout
7. API sketch (proposed)
7.1 Registration response extension
Existing response can be extended without breaking clients:
{
"ok": true,
"registration": {
"instanceId": "sc-example",
"instanceToken": "…",
"instanceSecret": "…"
},
"verification": {
"state": "registered_unverified",
"domainChallenge": {
"required": true,
"challengeId": "ch_123",
"challengeToken": "abc123…",
"verifyUrlPath": "/.well-known/sovereign-chd/sc-example",
"expiresAt": "2026-02-24T00:00:00Z"
}
}
}
7.2 Optional explicit verify endpoint
CHD can verify passively by fetch, or also expose:
POST /api/sovereign/v1/install/verify-domain
Input:
instanceId- optional
challengeId
CHD performs fetch and returns status.
This helps plugin/admin UI display clearer status.
8. Recommended policy gates
To keep UX smooth while reducing abuse:
- Registration:
- allow open or token-required (configurable)
- Entitlements sync:
- allow for registered instances
- Checkout link creation:
- require
domain_verified(recommended)
- require
- Grant workflows / higher trust operations:
- later require
qortal_verifiedand/or manual review
- later require
9. Connector hardening controls (independent of challenge)
Domain challenge should be combined with basic anti-abuse controls:
- Rate limit registration by IP
- Rate limit by normalized domain
- Cooldown for repeated attempts per domain
- Expire unverified registrations (e.g. 15–60 minutes)
- Reject localhost/private domains in production mode
- Cap pending unverified instances per IP/day
- Log registration + verification events
10. Backward compatibility / rollout
Phase 1 (compatibility)
- Add verification fields to registration response (optional)
- CHD stores verification state but does not enforce
- Existing plugins keep working unchanged
Phase 2 (soft enforcement)
- CHD warns on checkout when instance is not
domain_verified - Admin UI surfaces verification status and remediation steps
Phase 3 (policy enforcement)
- CHD blocks checkout for
registered_unverified(configurable) - Open registration remains possible but gated by verification
11. Future extension: Qortal ownership challenge
Longer term, add a second proof layer for the admin Qortal address:
- CHD issues a challenge tied to
adminQortalAddress - Admin proves control via Qortal-capable signing/decryption flow
- CHD marks instance
qortal_verified
This is better suited to a CHD admin plugin/admin cloud with Qortal tooling, not the connector alone.
12. Open questions
- Which public challenge URL path is easiest and most stable for Nextcloud deployments?
- Should checkout require
domain_verifiedimmediately or only in production mode? - Should verification use exact host match only, or allow canonical redirects?
- How long should challenge tokens remain valid?
- How should re-verification work when a cloud domain changes?