start work on spec doc
[pdns-pipe-nmc.git] / SPEC.md
1 % JSON Domain Format as Implemented by Pdns-Pipe-Nmc
2
3 ## Data Format
4
5 `DomObj` is a JSON object, specifically a `Map` (not an `Array`), or a
6 `String` containing a dotted quad (see Note below).
7
8 ### `DomObj` Attributes
9
10 | Key         | Type                 | Comment                         |
11 |-------------|----------------------|---------------------------------|
12 | service     | Array(SrvObj)        | Located two levels above pos.   |
13 | ip          | Array(String)        | Dotted quad "1.2.3.4"           |
14 | ip6         | Array(String)        | Semicolon format "DEAD::BEEF"   |
15 | tor         | String               | Onion name                      |
16 | i2p         | I2pObj               |                                 |
17 | freenet     | String               |                                 |
18 | alias       | String               | Nullifies other attributes      |
19 | translate   | String               | Nullifies other attributes      |
20 | email       | String               | Used in `SOA`                   |
21 | loc         | String               | Format suitable for `LOC`       |
22 | info        | JsonObj              | Currently unspecified           |
23 | ns          | Array(String)        | Domain names as in `NS`         |
24 | delegate    | String               | Nullifies other attributes      |
25 | import      | String               | "Deep" merges into current obj. |
26 | map         | Map(String:DomObj)   | Tree of subdomain objects       |
27 | fingerprint | Array(String)        |                                 |
28 | tls         | *TlsMap*             | See note below                  |
29 | ds          | Array(Array(String)) |                                 |
30
31 ### Notes:
32
33 * Any attribute specified as `Array(String)` may be present in the
34   JSON document as `String`, which is interpreted the same way as
35   an `Array` containing a single `String` element.
36 * In any place where `DomObj` is expected there may be a `String`, which
37   is interpreted as an IPv4 address. In other words, a string `"1.2.3.4"`
38   is interpreted the same way as the object `"{\"ip\":\"1.2.3.4\"}"`
39   Such "shorthand" DomObj can be present at the top level or as a value
40   in the `"map"` attribute.
41 * *TlsMap* is `Map(String:Map(String:Array(TlsObj)))`, where `TlsObj` is
42   a heterogenous Array of 3 elements: `[Int, String, Int]`. It is not
43   used by the DNS bridge.
44
45 ### SrvObj format
46
47 `SrvObj` is a heterogenous Array of fixed size containing 6 elements:
48
49 | N | Type   | Meaning  |
50 |---|--------|----------|
51 | 0 | String | Service  |
52 | 1 | String | Protocol |
53 | 2 | Int    | Priority |
54 | 3 | Int    | Weight   |
55 | 4 | Int    | Port     |
56 | 5 | String | Hostname |
57
58 ### Notes
59
60 * `Service` and `Protocol` are two elements of the domain name, without
61   the undescore '_'.
62 * `SrvObj` with Service `"smtp"`, Protocol `"tcp"` and Port `25` is also
63   interpteted as an `MX` DNS respource.
64 * When lookup is performed for `SRV` records at fqdn
65   `"_serv._proto.sub.dom.bit"`, domain object for `"sub.dom.bit"` must be
66   fetched, and in this object, `SrvObj`s for the Service `"serv"` and
67   Protocol `"proto"` selected from it.
68
69 ## Data Interpretation
70
71 Assuming a query for a subdomain of a basedomain in the `.bit` TLD
72 (subdomain possibly being empty), lookup starts by fetching the
73 "base" object for basedomain. The domain object is then transformed
74 by the following sequece applied recursively:
75
76 1. Value of the element of the `"map"` attribute with the key `""`
77    (empty string) is recursively merged into the base domain. The
78    `""` element of the `"map"` is removed from the result.
79 2. If attribute `"import"` does not exist in the resulting object,
80    recursion stops, and step 3 is performed on the result
81    If attribute `"import"` exists in the resulting object, lookup is
82    is performed for the value of this attribute, and fetched object
83    is recursively merged into the base domain. The `"import"` attribute
84    is removed from the result. Then the result is passed as base
85    domain to step 1.
86 3. If subdomain chain is empty, recursion stops, and step 4 is
87    performed on the result. If subdomain chain is not empty, next
88    element is taken out of the chain, and the `"map"` is looked
89    up for the element with the name matching the subdomain element.
90    The value of this element of the `"map"` is passed as base domain
91    to step 1. If matching element does not exist, lookup is considered
92    failed.
93 4. Domain object with all `""` map elements and all `"import"` data
94    merged is "normalized" by removal of attributes that are nullified
95    by the presence of other attributes.
96
97 Note that the process involves recursion nested to three levels.
98
99 ## Merging
100
101 When a domain object `sub` needs merging into a domain object `base`,
102 the following rules are applied:
103
104 * Of `String` and other "scalar" attributes, one is chosen, the value
105   from the `base` taking precedence.
106 * On `Array` attribtes, `union` operation is performed. (Of equal
107   elements, only one copy is left.)
108 * On `Map` attributes, recursive merge is performed. On the top level,
109   elemens with keys that are only present in either `base` or `sub`
110   object are all put into result. The values of the elements that are
111   present in both `base` and `sub` are merged according to the rules
112   applicable to their type.
113