mailschema 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -36
- package/bin/mailschema.js +40 -53
- package/dist/context.jsonld +50 -0
- package/dist/contract.schema.json +206 -0
- package/dist/core/artifacts.d.ts +11 -0
- package/dist/core/artifacts.js +30 -0
- package/dist/core/bundled.d.ts +4 -0
- package/dist/core/bundled.js +7 -0
- package/dist/core/contract.d.ts +69 -0
- package/dist/core/contract.js +253 -0
- package/dist/core/description.d.ts +45 -0
- package/dist/core/description.js +47 -0
- package/dist/core/implementation.d.ts +32 -0
- package/dist/core/implementation.js +25 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.js +9 -0
- package/dist/core/json.d.ts +23 -0
- package/dist/core/json.js +200 -0
- package/dist/core/patterns.d.ts +12 -0
- package/dist/core/patterns.js +165 -0
- package/dist/core/sha256.d.ts +2 -0
- package/dist/core/sha256.js +59 -0
- package/dist/core.schema.json +210 -0
- package/dist/implementation.schema.json +173 -0
- package/dist/index.d.ts +5 -9
- package/dist/index.js +5 -13
- package/dist/profile.json +27 -0
- package/package.json +9 -10
- package/dist/contribution.schema.json +0 -874
- package/dist/forms-0.1.schema.json +0 -329
- package/dist/map-0.2.jsonld +0 -91
- package/dist/map-0.2.schema.json +0 -1033
- package/dist/map.d.ts +0 -10
- package/dist/map.js +0 -20
- package/dist/model.d.ts +0 -95
- package/dist/model.js +0 -5
- package/dist/type-contract-0.2.schema.json +0 -179
- package/dist/validation.d.ts +0 -15
- package/dist/validation.js +0 -64
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// The regular expressions a contract's schemas may use: the subset that ECMA-262 (with the
|
|
2
|
+
// u flag) and other engines read alike, so every implementation enforces the same contract.
|
|
3
|
+
const SYNTAX_CHARACTERS = '^$\\.*+?()[]{}|/';
|
|
4
|
+
const CONTROL_ESCAPES = { t: 0x09, n: 0x0a, f: 0x0c, r: 0x0d };
|
|
5
|
+
const QUANTIFIERS = '*+?{';
|
|
6
|
+
/**
|
|
7
|
+
* Why a pattern is outside the portable subset, or undefined. The subset is printable ASCII
|
|
8
|
+
* text, with any other code point written as \uXXXX. It has literal characters and escaped
|
|
9
|
+
* syntax characters; \t, \n, \f, \r and \d, the ASCII digits; non-empty classes of literal or
|
|
10
|
+
* escaped members and ranges, with a literal hyphen only first or last; (?: groups;
|
|
11
|
+
* alternation; ^ and $; and one *, +, ?, {n}, {n,} or {n,m} after an atom. Other class
|
|
12
|
+
* escapes and the dot match different characters in different engines, and brackets, && or a
|
|
13
|
+
* stray brace inside a class, or a quantifier on a quantifier, are read differently or refused
|
|
14
|
+
* by one of them. ^ and $ anchor the whole value, as in ECMA-262; an engine whose anchors also
|
|
15
|
+
* match at line breaks must read them so.
|
|
16
|
+
*/
|
|
17
|
+
export function unportablePattern(pattern) {
|
|
18
|
+
if (!/^[\x20-\x7e]*$/.test(pattern))
|
|
19
|
+
return 'a character outside printable ASCII';
|
|
20
|
+
let at = 0;
|
|
21
|
+
// One escaped code point, the digit class outside a class, or a problem.
|
|
22
|
+
const escape = (inClass) => {
|
|
23
|
+
const next = pattern[at + 1];
|
|
24
|
+
if (next === undefined)
|
|
25
|
+
return 'a trailing backslash';
|
|
26
|
+
if (next === 'u') {
|
|
27
|
+
const digits = pattern.slice(at + 2, at + 6);
|
|
28
|
+
if (!/^[0-9a-fA-F]{4}$/.test(digits))
|
|
29
|
+
return 'a malformed \\u escape';
|
|
30
|
+
const code = parseInt(digits, 16);
|
|
31
|
+
if (code >= 0xd800 && code <= 0xdfff)
|
|
32
|
+
return 'a surrogate \\u escape';
|
|
33
|
+
at += 6;
|
|
34
|
+
return code;
|
|
35
|
+
}
|
|
36
|
+
at += 2;
|
|
37
|
+
if (next === 'd' && !inClass)
|
|
38
|
+
return -1;
|
|
39
|
+
if (Object.hasOwn(CONTROL_ESCAPES, next))
|
|
40
|
+
return CONTROL_ESCAPES[next];
|
|
41
|
+
if (SYNTAX_CHARACTERS.includes(next) || (inClass && next === '-'))
|
|
42
|
+
return next.charCodeAt(0);
|
|
43
|
+
return `the escape \\${next}`;
|
|
44
|
+
};
|
|
45
|
+
const characterClass = () => {
|
|
46
|
+
at += pattern[at + 1] === '^' ? 2 : 1;
|
|
47
|
+
// Each member's code point, or null for an unescaped hyphen.
|
|
48
|
+
const members = [];
|
|
49
|
+
while (pattern[at] !== ']') {
|
|
50
|
+
const char = pattern[at];
|
|
51
|
+
if (char === undefined)
|
|
52
|
+
return 'an unclosed character class';
|
|
53
|
+
if (char === '[')
|
|
54
|
+
return 'a bracket inside a class';
|
|
55
|
+
if (char === '&' && pattern[at + 1] === '&')
|
|
56
|
+
return '&& inside a class';
|
|
57
|
+
if (char === '\\') {
|
|
58
|
+
const code = escape(true);
|
|
59
|
+
if (typeof code === 'string')
|
|
60
|
+
return code;
|
|
61
|
+
members.push(code);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
members.push(char === '-' ? null : char.charCodeAt(0));
|
|
65
|
+
at += 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
at += 1;
|
|
69
|
+
if (!members.length)
|
|
70
|
+
return 'an empty character class';
|
|
71
|
+
for (let index = 0; index < members.length; index += 1) {
|
|
72
|
+
const low = members[index];
|
|
73
|
+
if (low === null) {
|
|
74
|
+
if (index !== 0 && index !== members.length - 1)
|
|
75
|
+
return 'an ambiguous hyphen in a class';
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (members[index + 1] !== null || index + 2 >= members.length)
|
|
79
|
+
continue;
|
|
80
|
+
const high = members[index + 2];
|
|
81
|
+
if (high === null)
|
|
82
|
+
return 'an ambiguous hyphen in a class';
|
|
83
|
+
if (high < low)
|
|
84
|
+
return 'a class range out of order';
|
|
85
|
+
index += 2;
|
|
86
|
+
if (members[index + 1] === null && index + 1 !== members.length - 1)
|
|
87
|
+
return 'an ambiguous hyphen in a class';
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const quantifier = () => {
|
|
91
|
+
if (pattern[at] === '{') {
|
|
92
|
+
const bounds = /^\{([0-9]{1,4})(?:(,)([0-9]{1,4})?)?\}/.exec(pattern.slice(at));
|
|
93
|
+
if (!bounds)
|
|
94
|
+
return 'a malformed {n,m} quantifier';
|
|
95
|
+
if (bounds[3] !== undefined && Number(bounds[3]) < Number(bounds[1]))
|
|
96
|
+
return 'a {n,m} quantifier with m below n';
|
|
97
|
+
at += bounds[0].length;
|
|
98
|
+
}
|
|
99
|
+
else
|
|
100
|
+
at += 1;
|
|
101
|
+
const next = pattern[at];
|
|
102
|
+
if (next !== undefined && QUANTIFIERS.includes(next))
|
|
103
|
+
return 'a quantifier on a quantifier';
|
|
104
|
+
};
|
|
105
|
+
const disjunction = (depth) => {
|
|
106
|
+
let quantifiable = false;
|
|
107
|
+
while (at < pattern.length) {
|
|
108
|
+
const char = pattern[at];
|
|
109
|
+
if (char === '|') {
|
|
110
|
+
at += 1;
|
|
111
|
+
quantifiable = false;
|
|
112
|
+
}
|
|
113
|
+
else if (char === ')') {
|
|
114
|
+
if (depth === 0)
|
|
115
|
+
return 'an unmatched )';
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
else if (char === '^' || char === '$') {
|
|
119
|
+
at += 1;
|
|
120
|
+
quantifiable = false;
|
|
121
|
+
}
|
|
122
|
+
else if (QUANTIFIERS.includes(char)) {
|
|
123
|
+
if (!quantifiable)
|
|
124
|
+
return char === '{' ? 'an unescaped {' : 'a quantifier with nothing to repeat';
|
|
125
|
+
const problem = quantifier();
|
|
126
|
+
if (problem)
|
|
127
|
+
return problem;
|
|
128
|
+
quantifiable = false;
|
|
129
|
+
}
|
|
130
|
+
else if (char === '(') {
|
|
131
|
+
if (!pattern.startsWith('(?:', at))
|
|
132
|
+
return 'a group other than (?:';
|
|
133
|
+
at += 3;
|
|
134
|
+
const problem = disjunction(depth + 1);
|
|
135
|
+
if (problem)
|
|
136
|
+
return problem;
|
|
137
|
+
if (pattern[at] !== ')')
|
|
138
|
+
return 'an unclosed group';
|
|
139
|
+
at += 1;
|
|
140
|
+
quantifiable = true;
|
|
141
|
+
}
|
|
142
|
+
else if (char === '[') {
|
|
143
|
+
const problem = characterClass();
|
|
144
|
+
if (problem)
|
|
145
|
+
return problem;
|
|
146
|
+
quantifiable = true;
|
|
147
|
+
}
|
|
148
|
+
else if (char === '\\') {
|
|
149
|
+
const code = escape(false);
|
|
150
|
+
if (typeof code === 'string')
|
|
151
|
+
return code;
|
|
152
|
+
quantifiable = true;
|
|
153
|
+
}
|
|
154
|
+
else if (char === '.')
|
|
155
|
+
return 'an unescaped dot';
|
|
156
|
+
else if (char === ']' || char === '}')
|
|
157
|
+
return `an unescaped ${char}`;
|
|
158
|
+
else {
|
|
159
|
+
at += 1;
|
|
160
|
+
quantifiable = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return disjunction(0);
|
|
165
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// SHA-256 (FIPS 180-4) over bytes, so the core needs no platform crypto and runs the same
|
|
2
|
+
// in Node, browsers and workers.
|
|
3
|
+
const K = Uint32Array.from([
|
|
4
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
5
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
6
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
7
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
8
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
9
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
10
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
11
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
12
|
+
]);
|
|
13
|
+
const rotate = (value, bits) => (value >>> bits) | (value << (32 - bits));
|
|
14
|
+
/** The lowercase hexadecimal SHA-256 of the bytes, or of the text's UTF-8 encoding. */
|
|
15
|
+
export function sha256(input) {
|
|
16
|
+
const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : input;
|
|
17
|
+
// The message, a 1 bit, zeros, and its length in bits as a 64-bit big-endian integer.
|
|
18
|
+
const padded = new Uint8Array(Math.ceil((bytes.length + 9) / 64) * 64);
|
|
19
|
+
padded.set(bytes);
|
|
20
|
+
padded[bytes.length] = 0x80;
|
|
21
|
+
const view = new DataView(padded.buffer);
|
|
22
|
+
view.setUint32(padded.length - 8, Math.floor(bytes.length / 0x20000000));
|
|
23
|
+
view.setUint32(padded.length - 4, (bytes.length * 8) >>> 0);
|
|
24
|
+
const hash = Uint32Array.from([
|
|
25
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
|
26
|
+
]);
|
|
27
|
+
const w = new Uint32Array(64);
|
|
28
|
+
for (let block = 0; block < padded.length; block += 64) {
|
|
29
|
+
for (let t = 0; t < 16; t += 1)
|
|
30
|
+
w[t] = view.getUint32(block + t * 4);
|
|
31
|
+
for (let t = 16; t < 64; t += 1) {
|
|
32
|
+
const s0 = rotate(w[t - 15], 7) ^ rotate(w[t - 15], 18) ^ (w[t - 15] >>> 3);
|
|
33
|
+
const s1 = rotate(w[t - 2], 17) ^ rotate(w[t - 2], 19) ^ (w[t - 2] >>> 10);
|
|
34
|
+
w[t] = w[t - 16] + s0 + w[t - 7] + s1;
|
|
35
|
+
}
|
|
36
|
+
let [a, b, c, d, e, f, g, h] = hash;
|
|
37
|
+
for (let t = 0; t < 64; t += 1) {
|
|
38
|
+
const t1 = h + (rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25)) + ((e & f) ^ (~e & g)) + K[t] + w[t];
|
|
39
|
+
const t2 = (rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22)) + ((a & b) ^ (a & c) ^ (b & c));
|
|
40
|
+
h = g;
|
|
41
|
+
g = f;
|
|
42
|
+
f = e;
|
|
43
|
+
e = (d + t1) >>> 0;
|
|
44
|
+
d = c;
|
|
45
|
+
c = b;
|
|
46
|
+
b = a;
|
|
47
|
+
a = (t1 + t2) >>> 0;
|
|
48
|
+
}
|
|
49
|
+
hash[0] += a;
|
|
50
|
+
hash[1] += b;
|
|
51
|
+
hash[2] += c;
|
|
52
|
+
hash[3] += d;
|
|
53
|
+
hash[4] += e;
|
|
54
|
+
hash[5] += f;
|
|
55
|
+
hash[6] += g;
|
|
56
|
+
hash[7] += h;
|
|
57
|
+
}
|
|
58
|
+
return Array.from(hash, (word) => word.toString(16).padStart(8, '0')).join('');
|
|
59
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://mailschema.org/artifacts/map-0.3/schemas/core.schema.json",
|
|
4
|
+
"title": "MAP 0.3 description shape; semantic checks in Core are additionally required",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"@context",
|
|
9
|
+
"@type",
|
|
10
|
+
"@id",
|
|
11
|
+
"profile",
|
|
12
|
+
"type",
|
|
13
|
+
"issuedAt",
|
|
14
|
+
"expiresAt",
|
|
15
|
+
"inLanguage",
|
|
16
|
+
"service",
|
|
17
|
+
"recipient",
|
|
18
|
+
"subject",
|
|
19
|
+
"terms",
|
|
20
|
+
"details",
|
|
21
|
+
"operations",
|
|
22
|
+
"human"
|
|
23
|
+
],
|
|
24
|
+
"properties": {
|
|
25
|
+
"@context": {
|
|
26
|
+
"const": "https://mailschema.org/contexts/map-0.3.jsonld"
|
|
27
|
+
},
|
|
28
|
+
"@type": {
|
|
29
|
+
"const": "MailAction"
|
|
30
|
+
},
|
|
31
|
+
"@id": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"minLength": 1,
|
|
34
|
+
"format": "uri",
|
|
35
|
+
"maxLength": 2048
|
|
36
|
+
},
|
|
37
|
+
"profile": {
|
|
38
|
+
"const": "https://mailschema.org/profiles/map/0.3"
|
|
39
|
+
},
|
|
40
|
+
"type": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"required": [
|
|
44
|
+
"id",
|
|
45
|
+
"version",
|
|
46
|
+
"contractDigest"
|
|
47
|
+
],
|
|
48
|
+
"properties": {
|
|
49
|
+
"id": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"minLength": 1,
|
|
52
|
+
"format": "uri",
|
|
53
|
+
"pattern": "^https://",
|
|
54
|
+
"maxLength": 2048
|
|
55
|
+
},
|
|
56
|
+
"version": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"minLength": 1,
|
|
59
|
+
"maxLength": 64
|
|
60
|
+
},
|
|
61
|
+
"contractDigest": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"minLength": 1,
|
|
64
|
+
"pattern": "^sha-256:[0-9a-f]{64}$"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"issuedAt": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"minLength": 1,
|
|
71
|
+
"format": "date-time",
|
|
72
|
+
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\dZ$"
|
|
73
|
+
},
|
|
74
|
+
"expiresAt": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"minLength": 1,
|
|
77
|
+
"format": "date-time",
|
|
78
|
+
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\dZ$"
|
|
79
|
+
},
|
|
80
|
+
"inLanguage": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"minLength": 1,
|
|
83
|
+
"maxLength": 255
|
|
84
|
+
},
|
|
85
|
+
"service": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"additionalProperties": false,
|
|
88
|
+
"required": [
|
|
89
|
+
"id"
|
|
90
|
+
],
|
|
91
|
+
"properties": {
|
|
92
|
+
"id": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"minLength": 1,
|
|
95
|
+
"format": "uri",
|
|
96
|
+
"pattern": "^https://(?![0-9.]+(:[0-9]+)?$)[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(:[0-9]{1,5})?$",
|
|
97
|
+
"maxLength": 2048
|
|
98
|
+
},
|
|
99
|
+
"tenant": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"minLength": 1,
|
|
102
|
+
"format": "uri",
|
|
103
|
+
"maxLength": 2048
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"recipient": {
|
|
108
|
+
"type": "string",
|
|
109
|
+
"minLength": 1,
|
|
110
|
+
"maxLength": 320
|
|
111
|
+
},
|
|
112
|
+
"subject": {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"additionalProperties": false,
|
|
115
|
+
"required": [
|
|
116
|
+
"id",
|
|
117
|
+
"title"
|
|
118
|
+
],
|
|
119
|
+
"properties": {
|
|
120
|
+
"id": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"minLength": 1,
|
|
123
|
+
"format": "uri",
|
|
124
|
+
"maxLength": 2048
|
|
125
|
+
},
|
|
126
|
+
"title": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"minLength": 1,
|
|
129
|
+
"maxLength": 2048
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
"terms": {
|
|
134
|
+
"type": "object",
|
|
135
|
+
"additionalProperties": false,
|
|
136
|
+
"required": [
|
|
137
|
+
"id",
|
|
138
|
+
"version"
|
|
139
|
+
],
|
|
140
|
+
"properties": {
|
|
141
|
+
"id": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"minLength": 1,
|
|
144
|
+
"format": "uri",
|
|
145
|
+
"maxLength": 2048
|
|
146
|
+
},
|
|
147
|
+
"version": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"minLength": 1,
|
|
150
|
+
"pattern": "^[ -~]+$",
|
|
151
|
+
"maxLength": 1024
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"details": {
|
|
156
|
+
"type": "object"
|
|
157
|
+
},
|
|
158
|
+
"operations": {
|
|
159
|
+
"type": "array",
|
|
160
|
+
"items": {
|
|
161
|
+
"type": "object",
|
|
162
|
+
"additionalProperties": false,
|
|
163
|
+
"required": [
|
|
164
|
+
"id"
|
|
165
|
+
],
|
|
166
|
+
"properties": {
|
|
167
|
+
"id": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"minLength": 1,
|
|
170
|
+
"pattern": "^[a-z][a-z0-9-]{0,63}$"
|
|
171
|
+
},
|
|
172
|
+
"capability": {
|
|
173
|
+
"type": "object",
|
|
174
|
+
"additionalProperties": false,
|
|
175
|
+
"required": [
|
|
176
|
+
"url"
|
|
177
|
+
],
|
|
178
|
+
"properties": {
|
|
179
|
+
"url": {
|
|
180
|
+
"type": "string",
|
|
181
|
+
"minLength": 1,
|
|
182
|
+
"format": "uri",
|
|
183
|
+
"pattern": "^https://[^/?#@]+([/?][^#]*)?$",
|
|
184
|
+
"maxLength": 4096
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"minItems": 1,
|
|
191
|
+
"maxItems": 32
|
|
192
|
+
},
|
|
193
|
+
"human": {
|
|
194
|
+
"type": "object",
|
|
195
|
+
"additionalProperties": false,
|
|
196
|
+
"required": [
|
|
197
|
+
"url"
|
|
198
|
+
],
|
|
199
|
+
"properties": {
|
|
200
|
+
"url": {
|
|
201
|
+
"type": "string",
|
|
202
|
+
"minLength": 1,
|
|
203
|
+
"format": "uri",
|
|
204
|
+
"pattern": "^https://[^/?#@]+([/?][^#]*)?$",
|
|
205
|
+
"maxLength": 4096
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://mailschema.org/artifacts/map-0.3/schemas/implementation.schema.json",
|
|
4
|
+
"title": "MAP implementation record",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"service",
|
|
9
|
+
"maintainer",
|
|
10
|
+
"type",
|
|
11
|
+
"operations",
|
|
12
|
+
"binding",
|
|
13
|
+
"status",
|
|
14
|
+
"documentation",
|
|
15
|
+
"evidence"
|
|
16
|
+
],
|
|
17
|
+
"dependentRequired": {
|
|
18
|
+
"artifact": ["format"],
|
|
19
|
+
"format": ["artifact"]
|
|
20
|
+
},
|
|
21
|
+
"properties": {
|
|
22
|
+
"service": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"minLength": 1,
|
|
25
|
+
"format": "uri",
|
|
26
|
+
"pattern": "^https://"
|
|
27
|
+
},
|
|
28
|
+
"maintainer": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"required": [
|
|
32
|
+
"name",
|
|
33
|
+
"url"
|
|
34
|
+
],
|
|
35
|
+
"properties": {
|
|
36
|
+
"name": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"minLength": 1
|
|
39
|
+
},
|
|
40
|
+
"url": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 1,
|
|
43
|
+
"format": "uri",
|
|
44
|
+
"pattern": "^https://"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"type": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": false,
|
|
51
|
+
"required": [
|
|
52
|
+
"id",
|
|
53
|
+
"version",
|
|
54
|
+
"contractDigest"
|
|
55
|
+
],
|
|
56
|
+
"properties": {
|
|
57
|
+
"id": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"minLength": 1,
|
|
60
|
+
"format": "uri",
|
|
61
|
+
"pattern": "^https://"
|
|
62
|
+
},
|
|
63
|
+
"version": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"minLength": 1
|
|
66
|
+
},
|
|
67
|
+
"contractDigest": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"pattern": "^sha-256:[0-9a-f]{64}$"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"operations": {
|
|
74
|
+
"type": "array",
|
|
75
|
+
"minItems": 1,
|
|
76
|
+
"uniqueItems": true,
|
|
77
|
+
"items": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"minLength": 1
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"binding": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"format": "uri",
|
|
85
|
+
"pattern": "^https://",
|
|
86
|
+
"description": "Identifier of the binding specification or documented service binding. It is not a request destination. Clients must explicitly support it."
|
|
87
|
+
},
|
|
88
|
+
"artifact": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"additionalProperties": false,
|
|
91
|
+
"required": [
|
|
92
|
+
"url",
|
|
93
|
+
"digest",
|
|
94
|
+
"digestMode"
|
|
95
|
+
],
|
|
96
|
+
"properties": {
|
|
97
|
+
"url": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"minLength": 1,
|
|
100
|
+
"format": "uri",
|
|
101
|
+
"pattern": "^https://"
|
|
102
|
+
},
|
|
103
|
+
"digest": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"pattern": "^sha-256:[0-9a-f]{64}$"
|
|
106
|
+
},
|
|
107
|
+
"digestMode": {
|
|
108
|
+
"enum": [
|
|
109
|
+
"canonical-json",
|
|
110
|
+
"bytes"
|
|
111
|
+
],
|
|
112
|
+
"description": "canonical-json hashes the RFC 8785 representation; bytes hashes the exact downloaded artifact. Both use SHA-256."
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"format": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"minLength": 1
|
|
119
|
+
},
|
|
120
|
+
"status": {
|
|
121
|
+
"enum": [
|
|
122
|
+
"Draft",
|
|
123
|
+
"Experimental",
|
|
124
|
+
"Stable",
|
|
125
|
+
"Deprecated",
|
|
126
|
+
"Superseded"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
"documentation": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"minLength": 1,
|
|
132
|
+
"format": "uri",
|
|
133
|
+
"pattern": "^https://"
|
|
134
|
+
},
|
|
135
|
+
"evidence": {
|
|
136
|
+
"type": "array",
|
|
137
|
+
"minItems": 1,
|
|
138
|
+
"items": {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"additionalProperties": false,
|
|
141
|
+
"required": [
|
|
142
|
+
"kind",
|
|
143
|
+
"url",
|
|
144
|
+
"summary"
|
|
145
|
+
],
|
|
146
|
+
"properties": {
|
|
147
|
+
"kind": {
|
|
148
|
+
"enum": [
|
|
149
|
+
"declaration",
|
|
150
|
+
"test-report"
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
"url": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"minLength": 1,
|
|
156
|
+
"format": "uri",
|
|
157
|
+
"pattern": "^https://"
|
|
158
|
+
},
|
|
159
|
+
"summary": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"minLength": 1
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"successor": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"minLength": 1,
|
|
169
|
+
"format": "uri",
|
|
170
|
+
"pattern": "^https://"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
/** Return an independent copy of the contribution JSON Schema (Draft 2020-12). */
|
|
7
|
-
export declare function getContributionSchema(): Record<string, unknown>;
|
|
8
|
-
/** Return the schema for an expanded Registry record, including attribution and history. */
|
|
9
|
-
export declare function getRecordSchema(): Record<string, unknown>;
|
|
1
|
+
/**
|
|
2
|
+
* Mail Action Protocol 0.3 processing: parse and check descriptions, type contracts and
|
|
3
|
+
* implementation records, and compute the RFC 8785 digests that identify contracts.
|
|
4
|
+
*/
|
|
5
|
+
export * from './core/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
/** Return an independent copy of the contribution JSON Schema (Draft 2020-12). */
|
|
7
|
-
export function getContributionSchema() {
|
|
8
|
-
return structuredClone(schema);
|
|
9
|
-
}
|
|
10
|
-
/** Return the schema for an expanded Registry record, including attribution and history. */
|
|
11
|
-
export function getRecordSchema() {
|
|
12
|
-
return { $schema: schema.$schema, $defs: structuredClone(schema.$defs), $ref: '#/$defs/record' };
|
|
13
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Mail Action Protocol 0.3 processing: parse and check descriptions, type contracts and
|
|
3
|
+
* implementation records, and compute the RFC 8785 digests that identify contracts.
|
|
4
|
+
*/
|
|
5
|
+
export * from './core/index.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "https://mailschema.org/profiles/map/0.3",
|
|
3
|
+
"name": "Mail Action Protocol 0.3",
|
|
4
|
+
"status": "working-draft",
|
|
5
|
+
"description": "An action description carried in Structured Email. A trusted service binding maps each decision to the service's existing operations, and the service enforces permission and exact terms. Types are defined by digest-bound contracts.",
|
|
6
|
+
"context": "https://mailschema.org/contexts/map-0.3.jsonld",
|
|
7
|
+
"schema": "https://mailschema.org/artifacts/map-0.3/schemas/core.schema.json",
|
|
8
|
+
"contractFormat": "https://mailschema.org/artifacts/map-0.3/schemas/contract.schema.json",
|
|
9
|
+
"specification": "https://mailschema.org/specification/core",
|
|
10
|
+
"artifacts": {
|
|
11
|
+
"context": {
|
|
12
|
+
"url": "https://mailschema.org/contexts/map-0.3.jsonld",
|
|
13
|
+
"sha256": "a51490d1fe8af695c14ea508aad88fd0429d18564791b6b52f3ab07d5c51aab3"
|
|
14
|
+
},
|
|
15
|
+
"schema": {
|
|
16
|
+
"url": "https://mailschema.org/artifacts/map-0.3/schemas/core.schema.json",
|
|
17
|
+
"sha256": "0ad09a6955a47e7a2c1c1eec0747a3e0b15c08a79860e90ce4e65da11983aeb3"
|
|
18
|
+
},
|
|
19
|
+
"contractFormat": {
|
|
20
|
+
"url": "https://mailschema.org/artifacts/map-0.3/schemas/contract.schema.json",
|
|
21
|
+
"sha256": "86bf057529c4fd2c7f0a880825774afeed31e9f7ba1d99760858a585fe28d18d"
|
|
22
|
+
},
|
|
23
|
+
"conformance": {
|
|
24
|
+
"url": "https://github.com/mailschema/mailschema/blob/main/conformance/map-0.3/README.md"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|