Class: DomainSanity::Policy
- Inherits:
-
Object
- Object
- DomainSanity::Policy
- Defined in:
- lib/domain_sanity/policy.rb
Overview
What counts as "valid" depends on who is asking. A certificate authority, a DNS zone editor, and a lenient form validator disagree about underscores, single-label names, private Public Suffix List entries, and script mixing.
Policy captures those choices as data instead of letting them accrete as
boolean keyword arguments on every method. Pass a preset symbol, a Hash of
overrides, or a Policy instance anywhere a policy: argument is accepted;
Policy.coerce turns all three into a Policy.
DomainSanity.valid?("_dmarc.example.com", policy: :dns_zone)
DomainSanity.valid?("host", policy: { allow_single_label: true })
Policy only governs how a host name is judged; it never makes valid? accept an IP, wildcard, or reverse-zone subject (those are distinct kinds with their own predicates).
Constant Summary collapse
- DEFAULTS =
Each field defaults to the strict (CA-style) choice: false, except allow_trailing_dot, since a single root dot denotes the same name.
{ allow_underscore: false, # permit "_" in labels (RFC 952/1123 forbid it) allow_single_label: false, # permit a bare host with no TLD ("intranet") allow_trailing_dot: true, # accept & normalize one trailing root dot include_private_suffixes: false, # treat private PSL entries (github.io) as suffixes allow_reserved_tld: false, # accept RFC 6761/6762/7686 special-use TLDs (.test, .local, .onion, .internal) require_single_script: false # reject confusable mixed-script IDN labels }.freeze
- FIELDS =
DEFAULTS.keys.freeze
- PRESET_NAMES =
The names of the built-in presets.
%i[ca_baseline dns_zone lenient].freeze
Class Method Summary collapse
-
.ca_baseline ⇒ Object
Strict, certificate-authority-style defaults.
-
.coerce(arg) ⇒ Object
Turn a Symbol preset, Hash of overrides, Policy, or nil into a Policy.
-
.dns_zone ⇒ Object
DNS zone editing: underscores, single-label hosts, and private suffixes are all fine here.
-
.lenient ⇒ Object
Everything permissive, including RFC 6761/6762/7686 special-use TLDs (.test, .local, .onion, .internal).
- .preset(name) ⇒ Object
- .presets ⇒ Object
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #hash ⇒ Object
-
#initialize(**opts) ⇒ Policy
constructor
A new instance of Policy.
- #to_h ⇒ Object
-
#with(**overrides) ⇒ Object
A copy with some fields overridden.
Constructor Details
#initialize(**opts) ⇒ Policy
Returns a new instance of Policy.
38 39 40 41 42 43 44 |
# File 'lib/domain_sanity/policy.rb', line 38 def initialize(**opts) unknown = opts.keys - FIELDS raise ArgumentError, "unknown policy option(s): #{unknown.join(", ")}" unless unknown.empty? DEFAULTS.each { |field, default| instance_variable_set(:"@#{field}", opts.fetch(field, default)) } freeze end |
Class Method Details
.ca_baseline ⇒ Object
Strict, certificate-authority-style defaults.
66 67 68 |
# File 'lib/domain_sanity/policy.rb', line 66 def ca_baseline new end |
.coerce(arg) ⇒ Object
Turn a Symbol preset, Hash of overrides, Policy, or nil into a Policy.
103 104 105 106 107 108 109 110 111 |
# File 'lib/domain_sanity/policy.rb', line 103 def coerce(arg) case arg when Policy then arg when Symbol then preset(arg) when Hash then ca_baseline.with(**arg) when nil then ca_baseline else raise ArgumentError, "cannot coerce #{arg.inspect} into a Policy" end end |
.dns_zone ⇒ Object
DNS zone editing: underscores, single-label hosts, and private suffixes are all fine here. Reserved special-use TLDs are still rejected - a real zone shouldn't contain them.
73 74 75 |
# File 'lib/domain_sanity/policy.rb', line 73 def dns_zone new(allow_underscore: true, allow_single_label: true, include_private_suffixes: true) end |
.lenient ⇒ Object
Everything permissive, including RFC 6761/6762/7686 special-use TLDs (.test, .local, .onion, .internal). Script safety stays off to avoid false positives.
80 81 82 83 84 85 86 87 |
# File 'lib/domain_sanity/policy.rb', line 80 def lenient new( allow_underscore: true, allow_single_label: true, include_private_suffixes: true, allow_reserved_tld: true ) end |
.preset(name) ⇒ Object
93 94 95 96 97 98 99 100 |
# File 'lib/domain_sanity/policy.rb', line 93 def preset(name) case name when :ca_baseline then ca_baseline when :dns_zone then dns_zone when :lenient then lenient else raise ArgumentError, "unknown policy preset: #{name.inspect}" end end |
.presets ⇒ Object
89 90 91 |
# File 'lib/domain_sanity/policy.rb', line 89 def presets PRESET_NAMES end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
55 56 57 |
# File 'lib/domain_sanity/policy.rb', line 55 def ==(other) other.is_a?(Policy) && other.to_h == to_h end |
#hash ⇒ Object
60 61 62 |
# File 'lib/domain_sanity/policy.rb', line 60 def hash to_h.hash end |
#to_h ⇒ Object
51 52 53 |
# File 'lib/domain_sanity/policy.rb', line 51 def to_h FIELDS.to_h { |field| [field, public_send(field)] } end |
#with(**overrides) ⇒ Object
A copy with some fields overridden.
47 48 49 |
# File 'lib/domain_sanity/policy.rb', line 47 def with(**overrides) self.class.new(**to_h.merge(overrides)) end |