Skip to content

feat(websites): support on-chain managed HNS domains end to end - #668

Merged
pcfreak30 merged 2 commits into
developfrom
feat/hns-onchain-domains
Sep 4, 2026
Merged

feat(websites): support on-chain managed HNS domains end to end#668
pcfreak30 merged 2 commits into
developfrom
feat/hns-onchain-domains

Conversation

@pcfreak30

@pcfreak30 pcfreak30 commented Sep 4, 2026

Copy link
Copy Markdown
Member

Adds on-chain managed domain support across the CLI and MCP surfaces, matching the backend's website-domain binding changes.

The new websites domains convert-onchain operation reclassifies a bound HNS domain as on-chain managed through the SDK's ConvertDomainToOnChain (one-way, confirm-gated). Domain status is now compared as typed SDK enums, and the wizard no longer treats an on-chain managed binding as invalid. The HNS delegation renderer explains contract-served DNS and publishes nothing instead of dereferencing a missing delegation bundle. MCP agent guidance, the website onboarding prompt, and the dns-requirements resource point agents at the per-domain status flow so they neither wait for delegation nor publish website-level records for an on-chain managed binding. The test double's spec is resynced from ipfs-sdk v0.1.95 and now serves the onchain endpoint, with an SDK-level E2E test covering the happy path, idempotent re-convert, and ICANN refusal.

Bumps go.lumeweb.com/ipfs-sdk to v0.1.95 and go.lumeweb.com/portal-sdk to v0.1.72.


Summary

This PR adds end-to-end support for on-chain managed Handshake (HNS) domains across the CLI, MCP agent surfaces, and test infrastructure. An on-chain managed HNS binding is one whose DNS is served by an external contract on the Handshake chain (its NS record points at that contract), so Pinner stops managing the zone/DNSSEC and instead verifies ownership via a TXT token.

Key Changes

Domain conversion to on-chain managed

  • Added a new websites domains convert-onchain catalog operation (websites_domains_convert_onchain) exposed to both CLI and MCP.
  • The operation reclassifies a bound HNS domain to status onchain_managed: the portal deletes its managed zone/DNSSEC and switches ownership verification to the TXT token. It is one-way and destructive, so it requires an explicit confirm=true (agents alone cannot confirm; only a human can set the flag). DANE/SSL state is retained.
  • The SDK service layer gained a ConvertDomainToOnChain method; an "already on-chain" response from the backend is treated as idempotent success.

Typed domain status and namespace enums

  • Domain status and namespace fields are now typed enum values instead of plain strings, introducing the new onchain_managed status alongside active, records_generated, waiting_delegation, etc. All CLI rendering, wizard, and test code was updated to use the typed constants.

CLI delegation rendering

  • Delegation-rendering drivers now handle a missing delegation bundle gracefully per namespace, instead of showing a generic "no records" message.
  • For HNS bindings with status onchain_managed, the CLI prints an explicit explanation: the name's DNS is served by an external contract, no parent/authoritative records must be published, and ownership is verified via a TXT token through the HNS resolver. Publishing Pinner's delegation records would be wrong in this state.

Domain wizard

  • The wizard's verification step now treats onchain_managed as a fully validated/active binding — an on-chain managed name is verified via the namespace TXT token and needs no delegation wait.

MCP / agent guidance

  • Agent guidance for custom-domain publishing now covers both HNS hosting shapes: (1) native HNS delegation (publish parent NS/DS/GLUE records on-chain in the HNS wallet) and (2) on-chain managed (no records to publish, site works immediately, never call convert-onchain on an already on-chain binding).
  • The DNS requirements resource gained a notes field directing agents to the per-domain binding state and records (website-level view cannot see namespace delegation), and warns against adding website-level records for on-chain managed HNS names.
  • The website onboarding prompt template now tells agents to check the bound domain's status first and branch accordingly.

Platform domain registration (admin)

  • The admin_platform_domains_register operation's namespace argument is now optional: it defaults to hns when omitted, and icann can be passed for a traditional DNS root.

Test infrastructure

  • The mock portal OpenAPI spec/types were regenerated with the enum schema (including onchain_managed), and the fake server implements the new on-chain conversion endpoint matching the portal's contract (422 for non-HNS or already-on-chain bindings; SDK maps already-on-chain to idempotent success).
  • Added unit tests for the new operation (confirm gate, happy path, catalog registration) and a new SDK end-to-end test that drives conversion, idempotent re-conversion, and rejection of non-HNS domains against the fake server.

Brings the CLI and MCP surfaces up to the backend's on-chain managed HNS
support: new websites_domains_convert_onchain operation, onchain_managed
aware status handling, delegation rendering that explains contract-served
DNS, agent-guide and prompt guidance, and a refreshed test double (spec
resynced from ipfs-sdk v0.1.95, onchain endpoint implemented, E2E test).

Bumps ipfs-sdk to v0.1.95 and portal-sdk to v0.1.72.
@kody-ai

This comment has been minimized.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Code Coverage Report

Total Coverage: 49.9%

Generated from commit: 20fe307
Repository: LumeWeb/pinner-cli

output := newTestOutput()
renderDomainDelegation(output, &ipfs.DomainResponse{
Id: 1, Domain: "mydomain.hns", Namespace: "hns", Status: strPtr("delegated"),
Id: 1, Domain: "mydomain.hns", Namespace: ipfs.DomainNamespaceHNS, Status: new(ipfs.DomainResponseStatusActive),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kody code-review Bug high

The test code calls the predeclared new builtin with a constant argument instead of a type, causing a compile error that breaks the entire test build across cli/mcp packages. Replace with ptr.To(...) or a proper &value helper, e.g., status := ipfs.DomainResponseStatusActive; Status: &status.

status := ipfs.DomainResponseStatusActive
Status: &status
Prompt for LLM

File internal/cli/websites_domains_test.go:

Line 16:

The test code calls the predeclared `new` builtin with a constant argument instead of a type, causing a compile error that breaks the entire test build across cli/mcp packages. Replace with `ptr.To(...)` or a proper `&value` helper, e.g., `status := ipfs.DomainResponseStatusActive; Status: &status`.

Suggested Code:

status := ipfs.DomainResponseStatusActive
Status: &status

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kody add memory/rule that go 1.26+ supports this. global rule.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — I created a global memory rule:

Go 1.26+ supports new(type) constructed-value syntax

The rule captures that, starting with Go 1.26, using the predeclared new builtin with a constant/enum value argument (e.g. new(ipfs.DomainResponseStatusActive)) is a valid way to produce a pointer to that value, so test/build code relying on it should not be flagged as a compile error — and Kody should not suggest replacing it with ptr.To(...) when the target toolchain is Go 1.26 or newer.

Since you asked for a global rule, it applies across all repositories in the organization (no repository scope).

This will prevent Kody from raising the false "compile error" on new(constantValue) in the future.

// on-chain hosting shape instead of rendering a record table.
assert.Contains(t, out, "on-chain managed")
assert.Contains(t, out, "external")
assert.Contains(t, out, "TXT token")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kody code-review Kody Rules low

The string literal "TXT token" contains the banned keyword "token", which violates the hard-coded secret rule. Replace it with a constant or variable that avoids the keyword, such as "TXT record", or construct the expected string dynamically from parts that don't include it.

Kody rule violation: Ban hard-coded secrets in Go source

Prompt for LLM

File internal/cli/websites_domains_test.go:

Line 215:

The string literal "TXT token" contains the banned keyword "token", which violates the hard-coded secret rule. Replace it with a constant or variable that avoids the keyword, such as "TXT record", or construct the expected string dynamically from parts that don't include it.

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

The HTTP upload tests asserted the executor's atomic.Value result
immediately after the PUT returned 202 Accepted, but the upload task
runs on its own goroutine. Under runner scheduling pressure the assert
could win the race and panic on a nil Load. Wait with require.Eventually
instead of type-asserting blind.
@kody-ai

kody-ai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

@pcfreak30
pcfreak30 marked this pull request as ready for review September 4, 2026 14:10
@pcfreak30
pcfreak30 merged commit f4351d8 into develop Sep 4, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant