Documentation
¶
Overview ¶
Package domain holds the entities, value objects and signal rules of Arnakoff. It is pure Go: no I/O, no clock and no logging (ADR 0002).
Index ¶
- Constants
- Variables
- func FormatDate(t time.Time) string
- type Company
- type Domain
- type Email
- type IBAN
- type Input
- type Kind
- type Level
- type Notice
- type NoticeKind
- type Phone
- type Registration
- type Report
- type SIREN
- type SIRET
- type Signal
- type Snapshot
- type SnapshotSpec
- type Source
- type SourceState
- type SourceStatus
Constants ¶
const NoSignalSummary = "Aucun signal connu dans nos sources"
NoSignalSummary is the summary of a report without any signal. It never says the input is safe: an absence from the sources proves nothing.
Variables ¶
var ( // ErrInvalidDomain means the input is not a domain name or a web URL. ErrInvalidDomain = errors.New("invalid domain") // ErrUnsupportedScheme means the input is a URL whose scheme is neither // http nor https. ErrUnsupportedScheme = fmt.Errorf("%w: unsupported URL scheme", ErrInvalidDomain) // ErrIPAddress means the host is an IP address, not a domain name. ErrIPAddress = fmt.Errorf("%w: IP address", ErrInvalidDomain) )
Domain errors. ErrUnsupportedScheme and ErrIPAddress also match ErrInvalidDomain with errors.Is.
var ( ErrSnapshotSource = errors.New("snapshot of another source") ErrSnapshotEmpty = errors.New("snapshot has no row") ErrSnapshotTooSmall = errors.New("snapshot has fewer rows than expected") ErrSnapshotColumnMissing = errors.New("missing column") ErrSnapshotShrunk = errors.New("shrunk by more than 20 %") )
Snapshot validation errors, checked with errors.Is.
var ErrInvalidEmail = errors.New("invalid email address")
ErrInvalidEmail means the input is not a single email address with a valid domain. Its message never quotes the input, which is personal data.
var ErrInvalidIBAN = errors.New("invalid IBAN")
ErrInvalidIBAN means the input is not a valid IBAN. Its message never quotes the input, which is personal data.
var ErrInvalidPhone = errors.New("invalid phone number")
ErrInvalidPhone means the input is not a single dialable phone number. Its message never quotes the input, which is personal data.
var ErrInvalidSIREN = errors.New("invalid SIREN")
ErrInvalidSIREN means the input is not a valid SIREN number.
var ErrInvalidSIRET = errors.New("invalid SIRET")
ErrInvalidSIRET means the input is not a valid SIRET number.
var ErrUnknownKind = errors.New("unknown input kind")
ErrUnknownKind means a name is not the name of an input kind.
var ErrUnrecognisedInput = errors.New("unrecognised input")
ErrUnrecognisedInput means the input is not a domain, a web URL, an email address, a phone number, an IBAN, a SIREN or a SIRET. When a kind was assumed, the error also wraps that kind's error, such as ErrInvalidIBAN. The message may quote part of an input read as a domain: log the kind of error, matched with errors.Is, not its text.
Functions ¶
func FormatDate ¶
FormatDate formats t as a French date, JJ/MM/AAAA, in t's own location. The caller picks the location (Europe/Paris for user-facing dates): the domain loads no time zone data.
Types ¶
type Company ¶ added in v0.21.0
type Company struct {
// Name is the company's full name, as SIRENE writes it.
Name string
// Created is when the company was created.
Created time.Time
// HeadOfficeClosed reports whether SIRENE lists the head office as
// closed.
HeadOfficeClosed bool
// HeadOfficeClosedOn is when the head office closed.
HeadOfficeClosedOn time.Time
}
Company holds what the SIRENE register publishes about a company and its head office (siège), and nothing about the people who run it. A zero time means the register did not publish that date.
type Domain ¶ added in v0.2.0
type Domain struct {
// contains filtered or unexported fields
}
Domain is a normalised domain name: lower case, A-labels, no final dot. The zero value is not a valid domain.
func ParseDomain ¶ added in v0.2.0
ParseDomain normalises a domain name or a web URL, as a user would paste it, into a Domain. A URL keeps its host only: credentials before the host are dropped, as a browser does ("https://amf-france.org@exemple.com" is exemple.com). Only http and https URLs are accepted, and IP addresses are reported with ErrIPAddress.
func (Domain) Registrable ¶ added in v0.2.0
Registrable returns the public suffix plus one label, the part a registrant controls: "groupe-ytria.com" for www.groupe-ytria.com, "atos-limited.co.uk" for www.atos-limited.co.uk. Private suffixes of the Public Suffix List count, so arnaque.github.io is its own registrable domain.
type Email ¶ added in v0.3.0
type Email struct {
// contains filtered or unexported fields
}
Email is an email address: the local part as written, the domain normalised by ParseDomain's rules. It is personal data: log Redacted, never String. The zero value is not a valid address.
func ParseEmail ¶ added in v0.3.0
ParseEmail reads a single RFC 5322 address, as a user would paste it from a message header ("Service client <contact@exemple.fr>"), and keeps the address only. The local part keeps its case, since RFC 5321 lets the receiving server tell cases apart. Nothing is checked over the network.
type IBAN ¶ added in v0.5.0
type IBAN struct {
// contains filtered or unexported fields
}
IBAN is an International Bank Account Number in electronic form, upper case without spaces. It is personal data: log Redacted, never String. The zero value is not a valid IBAN.
func ParseIBAN ¶ added in v0.5.0
ParseIBAN reads an IBAN as a user would write it, in electronic form ("FR1420041010050500013M02606") or paper form ("FR14 2004 1010 0505 0001 3M02 606"), in any case and with any spaces between characters. The country's length and format and the check digits are validated; the account is not checked for existing.
func (IBAN) Country ¶ added in v0.5.0
Country returns the ISO 3166-1 alpha-2 code of the country holding the account, the IBAN's first two letters, such as "FR".
func (IBAN) FrenchBankCode ¶ added in v0.5.0
FrenchBankCode returns the five-digit bank code ("code banque") of a French IBAN, the first five characters after the check digits, such as "20041". It reports false for an IBAN of any other country.
type Input ¶ added in v0.7.0
Input is a parsed input: a Domain, an Email, a Phone, an IBAN, a SIREN or a SIRET. Use a type switch to reach the value. String returns the normalised form, which is personal data for an Email, a Phone and an IBAN.
func ParseInput ¶ added in v0.7.0
ParseInput reads what a user pasted into an Input. A hint other than KindAuto forces that kind. KindAuto detects the kind from the input's shape, in this order:
- an "@" outside a URL: an email address ("contact@exemple.fr");
- only letters, digits and spaces, starting with two letters then two digits: an IBAN ("FR14 2004 …");
- only digits and spaces: nine digits are a SIREN, even with a wrong check digit; fourteen digits are a SIRET, or else a phone number ("0044 20 7946 0958"); any other count is a phone number;
- only digits, spaces and "+.-/()": a phone number ("+33 6 12 34 56 78");
- anything else: a domain or a web URL.
The error matches ErrUnrecognisedInput and, once a kind is assumed, the error of the first kind tried.
type Kind ¶ added in v0.7.0
type Kind uint8
Kind is the kind of an Input.
Input kinds. KindAuto, the zero value, is no kind: as a hint to ParseInput, it asks for the kind to be detected.
type Level ¶
type Level int
Level is the severity of a signal. Levels are ordered: a greater Level is more severe, so levels compare with the usual operators. The zero value is not a valid level.
const ( // LevelInfo is a neutral fact worth knowing. LevelInfo Level = iota + 1 // LevelAttention is a heuristic that calls for a check before acting. LevelAttention // LevelAlert is a fact an authority published, such as a blacklist entry. LevelAlert )
Signal levels, from the least to the most severe.
type Notice ¶ added in v0.22.0
type Notice struct {
// ID is the BODACC's identifier of the notice, such as "A202601993983".
ID string
// Kind is the notice's family.
Kind NoticeKind
// Published is the day the BODACC published the notice.
Published time.Time
}
Notice is a notice the BODACC published about a company, and nothing about the people it names.
type NoticeKind ¶ added in v0.22.0
type NoticeKind int
NoticeKind is the family of a BODACC notice that bears on a company's state. Each is a BODACC family as the BODACC names it, kept apart: what a family means for a signal is the signal's rule.
const ( // NoticeCollectiveProcedure is « Procédures collectives ». NoticeCollectiveProcedure NoticeKind = iota + 1 // NoticeRadiation is « Radiations ». NoticeRadiation // NoticeConciliation is « Procédures de conciliation ». NoticeConciliation // NoticeProfessionalRecovery is « Procédures de rétablissement // professionnel ». NoticeProfessionalRecovery )
The BODACC families read; the BODACC's own label is quoted.
type Phone ¶ added in v0.4.0
type Phone struct {
// contains filtered or unexported fields
}
Phone is a phone number in E.164 form. It is personal data: log Redacted, never String. The zero value is not a valid number.
func ParsePhone ¶ added in v0.4.0
ParsePhone reads a phone number as a user would write it, in French national form ("06 12 34 56 78") or international form ("+33 6 12 34 56 78", "0033 6 12 34 56 78"), with spaces, dots, dashes, slashes or brackets between digits. National overseas numbers ("0690 12 34 56") get their overseas country code. Letters, extensions and short numbers are rejected. The number is checked for a plausible length, not for being in service: that is ARCEP's numbering plan's job.
func (Phone) CountryCode ¶ added in v0.4.0
CountryCode returns the country calling code, such as 33.
func (Phone) FrenchNational ¶ added in v0.4.0
FrenchNational returns the number as dialled within France, ten digits starting with 0 ("0612345678"), the form ARCEP's numbering plan ranges use. It reports false for a number outside the French numbering plan (metropolitan France and the overseas departments and regions above).
type Registration ¶ added in v0.20.0
type Registration struct {
// Registered is when the domain was first registered.
Registered time.Time
// LastChanged is when the registry last changed the domain's record.
LastChanged time.Time
}
Registration holds the dates a domain registry publishes about a registrable domain, and nothing about its holder. A zero time means the registry did not publish that date.
type Report ¶
type Report struct {
// contains filtered or unexported fields
}
Report is the result of checking one input: its signals, most severe first, and the state of each source consulted. A Report is immutable: its accessors return copies.
func NewReport ¶
func NewReport(input string, signals []Signal, sources []SourceState) Report
NewReport builds the report for the normalised input. A signal repeating the code, source and message of an earlier one is dropped. Signals are sorted by level, most severe first; signals of equal level keep their order. The slices are copied, the caller's are left untouched.
func (Report) Sources ¶
func (r Report) Sources() []SourceState
Sources returns a copy of the state of each source.
type SIREN ¶ added in v0.6.0
type SIREN struct {
// contains filtered or unexported fields
}
SIREN is the nine-digit number the SIRENE register gives to a company. The zero value is not a valid SIREN.
func ParseSIREN ¶ added in v0.6.0
ParseSIREN reads a SIREN as a user would write it, nine digits alone ("120027016") or in groups ("120 027 016") with any spaces between them. The Luhn check digit is validated; the company is not checked for existing.
type SIRET ¶ added in v0.6.0
type SIRET struct {
// contains filtered or unexported fields
}
SIRET is the fourteen-digit number the SIRENE register gives to an establishment: the company's SIREN followed by a five-digit NIC. The zero value is not a valid SIRET.
func ParseSIRET ¶ added in v0.6.0
ParseSIRET reads a SIRET as a user would write it, fourteen digits alone ("12002701600563") or in groups ("120 027 016 00563") with any spaces between them. The SIREN part and the whole number are checked; the establishment is not checked for existing.
func (SIRET) NIC ¶ added in v0.6.0
NIC returns the five-digit establishment number ("numéro interne de classement"), the last five digits, such as "00563".
type Signal ¶
type Signal struct {
// Code is the stable snake_case identifier of the rule, such as
// "amf_blacklist". It is part of the public contract.
Code string
// Level is the severity of the signal.
Level Level
// Message is one factual French sentence stating what was observed.
Message string
// Advice is an optional French sentence telling the user what to do.
Advice string
// Source is the upstream source the fact comes from.
Source Source
// SourceURL is the public page where the fact can be checked.
SourceURL string
// ObservedAt is when the fact was read from the source.
ObservedAt time.Time
}
Signal is one sourced fact about a checked input. Every field but Advice is set: a signal without its source and observation date is not published.
type Snapshot ¶ added in v0.13.0
type Snapshot struct {
// Source is the upstream source the file comes from.
Source Source
// Header names the fields of each row, in order.
Header []string
// Rows holds the entries, one slice of fields per row.
Rows [][]string
// FetchedAt is when the file was downloaded.
FetchedAt time.Time
// Newest is the date of the most recent entry, zero when the source
// dates none.
Newest time.Time
}
Snapshot is one validated copy of an upstream file, as rows of fields under a header. It is read-only once built: readers share it.
type SnapshotSpec ¶ added in v0.13.0
SnapshotSpec is what a connector declares about its source's file: the columns it reads and the least number of rows a sane file holds.
type Source ¶
type Source string
Source names an upstream data source, as shown to users ("AMF", "SIRENE").
type SourceState ¶
type SourceState struct {
Source Source
Status SourceStatus
}
SourceState is the status of one source in a report.
type SourceStatus ¶
type SourceStatus int
SourceStatus tells how a source took part in a check. The zero value is not a valid status.
const ( // SourceOK means the source was consulted. SourceOK SourceStatus = iota + 1 // of a signal from it proves nothing. SourceUnavailable // SourceNotApplicable means the source does not cover this input type. SourceNotApplicable )
Source statuses.
func (SourceStatus) String ¶
func (s SourceStatus) String() string
String returns the status's stable French code: "ok", "indisponible" or "non applicable".