feat(dns): add service-level name verification

This commit is contained in:
Virgil 2026-04-02 03:38:34 +00:00
parent c185eb4a83
commit fe564931cb
4 changed files with 67 additions and 0 deletions

12
lns.go
View file

@ -56,3 +56,15 @@ func (s *Service) Resolve(name any) (primitives.Hash, error) {
return dns.NewService(opts...).Resolve(name)
}
// Verify reports whether a .lthn name is valid after canonicalisation.
//
// This keeps the service-level API aligned with the DNS resolver helpers.
func (s *Service) Verify(name any) bool {
opts := make([]dns.ServiceOption, 0, 1)
if s != nil && s.ServiceRuntime != nil {
opts = append(opts, dns.WithCore(s.Core()))
}
return dns.NewService(opts...).Verify(name)
}

View file

@ -54,3 +54,24 @@ func TestServiceResolveRejectsInvalidNames(t *testing.T) {
t.Fatal("Resolve should reject unsupported input types")
}
}
func TestServiceVerify(t *testing.T) {
svc := &Service{}
cases := []struct {
name any
ok bool
}{
{name: "Foo-Bar.lthn", ok: true},
{name: []byte("Foo-Bar.lthn"), ok: true},
{name: "foo.bar.lthn", ok: false},
{name: "foo-", ok: false},
{name: 123, ok: false},
}
for _, tc := range cases {
if got := svc.Verify(tc.name); got != tc.ok {
t.Fatalf("Verify(%v) = %v, want %v", tc.name, got, tc.ok)
}
}
}

View file

@ -73,6 +73,19 @@ func (s *Service) Resolve(name any) (primitives.Hash, error) {
return covenant.HashString(normalized)
}
// Verify reports whether a .lthn name is valid after canonicalisation.
//
// This mirrors Resolve's input handling but returns a boolean so callers can
// validate user input without allocating or hashing.
func (s *Service) Verify(name any) bool {
normalized, ok := canonicalizeName(name)
if !ok {
return false
}
return covenant.VerifyString(normalized)
}
func canonicalizeName(name any) (string, bool) {
var value string

View file

@ -54,3 +54,24 @@ func TestResolveRejectsInvalidNames(t *testing.T) {
t.Fatal("Resolve should reject unsupported input types")
}
}
func TestVerify(t *testing.T) {
svc := NewService()
cases := []struct {
name any
ok bool
}{
{name: "Foo-Bar.lthn", ok: true},
{name: []byte("Foo-Bar.lthn"), ok: true},
{name: "foo.bar.lthn", ok: false},
{name: "foo-", ok: false},
{name: 123, ok: false},
}
for _, tc := range cases {
if got := svc.Verify(tc.name); got != tc.ok {
t.Fatalf("Verify(%v) = %v, want %v", tc.name, got, tc.ok)
}
}
}