@toa.io/extensions.exposition 1.0.0-alpha.5 → 1.0.0-alpha.6

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.
Files changed (78) hide show
  1. package/components/identity.basic/manifest.toa.yaml +2 -0
  2. package/components/identity.federation/manifest.toa.yaml +0 -6
  3. package/components/identity.roles/manifest.toa.yaml +1 -0
  4. package/documentation/io.md +56 -0
  5. package/documentation/query.md +9 -7
  6. package/documentation/tree.md +22 -4
  7. package/features/access.feature +11 -1
  8. package/features/annotation.feature +1 -0
  9. package/features/body.feature +1 -0
  10. package/features/cache.feature +3 -0
  11. package/features/directives.feature +2 -0
  12. package/features/dynamic.feature +14 -7
  13. package/features/errors.feature +3 -2
  14. package/features/etag.feature +1 -0
  15. package/features/identity.basic.feature +23 -0
  16. package/features/identity.federation.feature +3 -5
  17. package/features/identity.roles.feature +1 -0
  18. package/features/identity.tokens.feature +3 -0
  19. package/features/io.feature +167 -0
  20. package/features/octets.entries.feature +2 -0
  21. package/features/octets.feature +2 -0
  22. package/features/octets.meta.feature +4 -3
  23. package/features/octets.workflows.feature +1 -0
  24. package/features/queries.feature +9 -1
  25. package/features/response.feature +3 -0
  26. package/features/routes.feature +17 -10
  27. package/features/steps/components/pots/manifest.toa.yaml +2 -0
  28. package/features/steps/components/users/manifest.toa.yaml +1 -0
  29. package/features/steps/components/users.properties/manifest.toa.yaml +1 -0
  30. package/features/vary.feature +33 -3
  31. package/package.json +7 -7
  32. package/schemas/io/input.cos.yaml +3 -0
  33. package/schemas/io/message.cos.yaml +5 -0
  34. package/schemas/io/output.cos.yaml +5 -0
  35. package/source/HTTP/Server.ts +2 -2
  36. package/source/directives/auth/Authorization.ts +3 -3
  37. package/source/directives/index.ts +4 -3
  38. package/source/directives/io/Directive.ts +11 -0
  39. package/source/directives/io/IO.ts +43 -0
  40. package/source/directives/io/Input.ts +50 -0
  41. package/source/directives/io/Message.ts +1 -0
  42. package/source/directives/io/Output.ts +69 -0
  43. package/source/directives/io/index.ts +3 -0
  44. package/source/directives/io/schemas.ts +12 -0
  45. package/source/directives/vary/embeddings/Header.ts +8 -6
  46. package/source/root.ts +5 -0
  47. package/transpiled/HTTP/Server.js +2 -2
  48. package/transpiled/HTTP/Server.js.map +1 -1
  49. package/transpiled/directives/auth/Authorization.js +3 -3
  50. package/transpiled/directives/auth/Authorization.js.map +1 -1
  51. package/transpiled/directives/index.js +4 -3
  52. package/transpiled/directives/index.js.map +1 -1
  53. package/transpiled/directives/io/Directive.d.ts +8 -0
  54. package/transpiled/directives/io/Directive.js +3 -0
  55. package/transpiled/directives/io/Directive.js.map +1 -0
  56. package/transpiled/directives/io/IO.d.ts +9 -0
  57. package/transpiled/directives/io/IO.js +33 -0
  58. package/transpiled/directives/io/IO.js.map +1 -0
  59. package/transpiled/directives/io/Input.d.ts +11 -0
  60. package/transpiled/directives/io/Input.js +63 -0
  61. package/transpiled/directives/io/Input.js.map +1 -0
  62. package/transpiled/directives/io/Message.d.ts +1 -0
  63. package/transpiled/directives/io/Message.js +3 -0
  64. package/transpiled/directives/io/Message.js.map +1 -0
  65. package/transpiled/directives/io/Output.d.ts +13 -0
  66. package/transpiled/directives/io/Output.js +76 -0
  67. package/transpiled/directives/io/Output.js.map +1 -0
  68. package/transpiled/directives/io/index.d.ts +2 -0
  69. package/transpiled/directives/io/index.js +6 -0
  70. package/transpiled/directives/io/index.js.map +1 -0
  71. package/transpiled/directives/io/schemas.d.ts +7 -0
  72. package/transpiled/directives/io/schemas.js +14 -0
  73. package/transpiled/directives/io/schemas.js.map +1 -0
  74. package/transpiled/directives/vary/embeddings/Header.js +8 -6
  75. package/transpiled/directives/vary/embeddings/Header.js.map +1 -1
  76. package/transpiled/root.js +5 -0
  77. package/transpiled/root.js.map +1 -1
  78. package/transpiled/tsconfig.tsbuildinfo +1 -1
@@ -42,9 +42,11 @@ configuration:
42
42
  exposition:
43
43
  isolated: true
44
44
  /:
45
+ io:output: [id]
45
46
  anonymous: true
46
47
  POST: incept
47
48
  /:id:
49
+ io:output: [id]
48
50
  auth:role: system:identity:basic
49
51
  auth:scheme: basic
50
52
  auth:id: id
@@ -93,9 +93,3 @@ configuration:
93
93
  - sub
94
94
  additionalProperties: false
95
95
  additionalProperties: false
96
-
97
- exposition:
98
- isolated: true
99
- /:
100
- anonymous: true
101
- POST: incept
@@ -28,5 +28,6 @@ exposition:
28
28
  auth:role: system:identity:roles
29
29
  POST: transit
30
30
  GET:
31
+ io:output: true
31
32
  auth:id: identity
32
33
  endpoint: list
@@ -0,0 +1,56 @@
1
+ # I/O restrictions
2
+
3
+ The Exposition comes with `io` directives to control access to the operation's input and output
4
+ properties.
5
+
6
+ ## `io:input`
7
+
8
+ The `io:input` optional directive contains a list of properties that are allowed to be specified in
9
+ the request body.
10
+
11
+ ```yaml
12
+ POST:
13
+ endpoint: create
14
+ io:input: [name, location]
15
+ ```
16
+
17
+ The list must be a valid subset of the operation's input properties.
18
+
19
+ If `io:input` is specified and the request body is not an object, or contains properties that are
20
+ not in the list, the request will be rejected with a `400` status code.
21
+
22
+ > Therefore, `io:input` is only applicable to operations which input is an object or an
23
+ > array of objects.
24
+
25
+ ## `io:output`
26
+
27
+ The `io:output` mandatory directive contains a list of properties that are allowed to be included in
28
+ the response body.
29
+
30
+ ```yaml
31
+ GET:
32
+ endpoint: observe
33
+ io:output: [name, location]
34
+ ```
35
+
36
+ When an operation does not return an object (e.g., a primitive or a stream), or an object is dynamic
37
+ and its properties are not known in advance, `io:output` may have a value of `true` to disable
38
+ output restrictions.
39
+
40
+ ```yaml
41
+ GET:
42
+ endpoint: proxy
43
+ io:output: true
44
+ ```
45
+
46
+ If a method declaration lacks `io:output` directive, it will trigger a warning, and its
47
+ response will consistently be empty.
48
+ If this behavior is intended, a `false` value can be employed to suppress warnings.
49
+
50
+ ```yaml
51
+ GET:
52
+ endpoint: conceal
53
+ io:output: false
54
+ ```
55
+
56
+ Output restrictions are not applied to stream responses and errors.
@@ -6,10 +6,10 @@
6
6
  id?: string
7
7
  criteria?: string
8
8
  sort?: string
9
- omit?: [integer]
10
- limit?: [integer]
9
+ omit?: integer
10
+ limit?: integer
11
11
  selectors?: string[]
12
- projection?: [string]
12
+ projection?: string[]
13
13
  ```
14
14
 
15
15
  ```yaml
@@ -251,9 +251,9 @@ PUT /dummies/5e82ed5e/ HTTP/1.1
251
251
  if-match: "1"
252
252
 
253
253
  foo: baz
254
+ ```
254
255
 
255
- ---
256
-
256
+ ```http
257
257
  200 OK
258
258
  ```
259
259
 
@@ -262,8 +262,10 @@ PUT /dummies/5e82ed5e/ HTTP/1.1
262
262
  if-match: "never"
263
263
 
264
264
  foo: baz
265
+ ```
265
266
 
266
- ---
267
-
267
+ ```http
268
268
  412 Precondition Failed
269
269
  ```
270
+
271
+ The value within the quotes is mapped to the `version` property of operation call query.
@@ -102,7 +102,7 @@ HTTP methods can only be mapped to operations of the corresponding types.
102
102
  | `GET` | **Observation**<br/>**Computation** |
103
103
  | `PATCH` | **Assignment**<br/>**Effect** |
104
104
 
105
- As method mapping is unambiguous for Observation, Assignent, and Computation, a consice syntax is
105
+ As method mapping is unambiguous for Observation, Assignment, and Computation, a concise syntax is
106
106
  available:
107
107
 
108
108
  ```yaml
@@ -110,7 +110,23 @@ available:
110
110
  /items/:id: [observe, assign]
111
111
  ```
112
112
 
113
- ### Intermediate Nodes
113
+ ### Projections
114
+
115
+ A Method can have a `projection` key that specifies the fields of the operation result to be
116
+ included in the response.
117
+
118
+ ```yaml
119
+ /teapots:
120
+ GET:
121
+ endpoint: select
122
+ projection:
123
+ - name
124
+ - state
125
+ ```
126
+
127
+ > `id` is always included in the projection.
128
+
129
+ ## Intermediate Nodes
114
130
 
115
131
  An RTD Node that has a Route with a key `/` is an _intermediate_ Node.
116
132
  Intermediate Nodes must not have Methods as they are unreachable.
@@ -124,8 +140,10 @@ Intermediate Nodes must not have Methods as they are unreachable.
124
140
 
125
141
  ## Directives
126
142
 
127
- RTD Directives are declared using RTD node or Method keys following the `{family}:{directive}` pattern and can be used
128
- to add or modify the behavior of request processing. Directive declarations are applied to the RTD node where they are
143
+ RTD Directives are declared using RTD node or Method keys following the `{family}:{directive}`
144
+ pattern and can be used
145
+ to add or modify the behavior of request processing. Directive declarations are applied to the RTD
146
+ node where they are
129
147
  declared and to all nested nodes.
130
148
 
131
149
  ```yaml
@@ -30,6 +30,7 @@ Feature: Access authorization
30
30
  Given the annotation:
31
31
  """yaml
32
32
  /:
33
+ io:output: true
33
34
  auth:anonymous: true
34
35
  GET:
35
36
  dev:stub:
@@ -71,6 +72,7 @@ Feature: Access authorization
71
72
  Given the annotation:
72
73
  """yaml
73
74
  /:
75
+ io:output: true
74
76
  /:id:
75
77
  auth:id: id
76
78
  GET:
@@ -109,6 +111,7 @@ Feature: Access authorization
109
111
  And the annotation:
110
112
  """yaml
111
113
  /:
114
+ io:output: true
112
115
  auth:role: developer
113
116
  GET:
114
117
  dev:stub:
@@ -146,6 +149,7 @@ Feature: Access authorization
146
149
  And the annotation:
147
150
  """yaml
148
151
  /:
152
+ io:output: true
149
153
  /:
150
154
  auth:role: developer:rust:junior # role scope matches
151
155
  /nested:
@@ -190,6 +194,7 @@ Feature: Access authorization
190
194
  - developer
191
195
  - admin
192
196
  GET:
197
+ io:output: true
193
198
  dev:stub:
194
199
  access: granted!
195
200
  """
@@ -215,6 +220,7 @@ Feature: Access authorization
215
220
  And the annotation:
216
221
  """yaml
217
222
  /:
223
+ io:output: true
218
224
  /rust/:id:
219
225
  auth:rule:
220
226
  id: id
@@ -257,6 +263,7 @@ Feature: Access authorization
257
263
  Given the annotation:
258
264
  """yaml
259
265
  /:
266
+ io:output: true
260
267
  /:id:
261
268
  auth:id: id
262
269
  GET:
@@ -295,6 +302,7 @@ Feature: Access authorization
295
302
  Given the annotation:
296
303
  """yaml
297
304
  /:
305
+ io:output: true
298
306
  auth:role: developer
299
307
  GET:
300
308
  dev:stub:
@@ -335,6 +343,7 @@ Feature: Access authorization
335
343
  Given the annotation:
336
344
  """yaml
337
345
  /:
346
+ io:output: true
338
347
  /:id:
339
348
  auth:scheme: basic
340
349
  auth:id: id
@@ -374,7 +383,8 @@ Feature: Access authorization
374
383
 
375
384
  Given the annotation:
376
385
  """yaml
377
- anonymous: true
386
+ /:
387
+ anonymous: true
378
388
  """
379
389
  When the following request is received:
380
390
  """
@@ -4,6 +4,7 @@ Feature: Annotation
4
4
  Given the annotation:
5
5
  """yaml
6
6
  /:
7
+ io:output: true
7
8
  anonymous: true
8
9
  /foo:
9
10
  GET:
@@ -25,6 +25,7 @@ Feature: Request body
25
25
  """yaml
26
26
  exposition:
27
27
  /:name:
28
+ io:output: true
28
29
  GET: <operation>
29
30
  """
30
31
  When the following request is received:
@@ -14,6 +14,7 @@ Feature: Caching
14
14
  Given the annotation:
15
15
  """yaml
16
16
  /:
17
+ io:output: true
17
18
  anonymous: true
18
19
  GET:
19
20
  cache:control: max-age=60000
@@ -37,6 +38,7 @@ Feature: Caching
37
38
  Given the annotation:
38
39
  """yaml
39
40
  /:
41
+ io:output: true
40
42
  cache:control: max-age=30000
41
43
  GET:
42
44
  anonymous: true
@@ -120,6 +122,7 @@ Feature: Caching
120
122
  Given the annotation:
121
123
  """yaml
122
124
  /:
125
+ io:output: true
123
126
  auth:role: developer
124
127
  cache:exact: max-age=60000, public
125
128
  GET:
@@ -4,6 +4,7 @@ Feature: Directives
4
4
  Given the annotation:
5
5
  """yaml
6
6
  /:
7
+ io:output: true
7
8
  anonymous: true
8
9
  GET:
9
10
  dev:stub:
@@ -26,6 +27,7 @@ Feature: Directives
26
27
  Given the annotation:
27
28
  """yaml
28
29
  /:
30
+ io:output: true
29
31
  anonymous: true
30
32
  dev:stub:
31
33
  hello: again
@@ -11,6 +11,7 @@ Feature: Dynamic tree updates
11
11
  """yaml
12
12
  exposition:
13
13
  /:
14
+ io:output: true
14
15
  isolated: true
15
16
  GET: enumerate
16
17
  """
@@ -27,6 +28,7 @@ Feature: Dynamic tree updates
27
28
  """yaml
28
29
  exposition:
29
30
  /:
31
+ io:output: true
30
32
  GET: enumerate
31
33
  """
32
34
  When the following request is received:
@@ -44,19 +46,22 @@ Feature: Dynamic tree updates
44
46
  """yaml
45
47
  exposition:
46
48
  /:id:
49
+ io:output: true
47
50
  GET: observe
48
51
  """
49
52
  Then the `pots` is stopped
50
53
  Then the `pots` is running with the following manifest:
51
54
  """yaml
52
55
  exposition:
53
- /:id:
54
- GET: observe
55
- /big:
56
- GET:
57
- endpoint: enumerate
58
- query:
59
- criteria: volume>200
56
+ /:
57
+ io:output: true
58
+ /:id:
59
+ GET: observe
60
+ /big:
61
+ GET:
62
+ endpoint: enumerate
63
+ query:
64
+ criteria: volume>200
60
65
  """
61
66
  When the following request is received:
62
67
  """
@@ -73,6 +78,7 @@ Feature: Dynamic tree updates
73
78
  """yaml
74
79
  exposition:
75
80
  /big:
81
+ io:output: true
76
82
  GET:
77
83
  endpoint: enumerate
78
84
  query:
@@ -83,6 +89,7 @@ Feature: Dynamic tree updates
83
89
  """yaml
84
90
  exposition:
85
91
  /big:
92
+ io:output: true
86
93
  GET:
87
94
  endpoint: enumerate
88
95
  query:
@@ -46,7 +46,7 @@ Feature: Errors
46
46
  accept: application/yaml
47
47
  """
48
48
  Then the following reply is sent:
49
- """http
49
+ """
50
50
  405 Method Not Allowed
51
51
  """
52
52
 
@@ -57,7 +57,7 @@ Feature: Errors
57
57
  accept: application/yaml
58
58
  """
59
59
  Then the following reply is sent:
60
- """http
60
+ """
61
61
  501 Not Implemented
62
62
  """
63
63
 
@@ -197,6 +197,7 @@ Feature: Errors
197
197
  """yaml
198
198
  /:
199
199
  GET:
200
+ io:output: true
200
201
  anonymous: true
201
202
  dev:stub: hello
202
203
  """
@@ -5,6 +5,7 @@ Feature: Optimistic concurrency control
5
5
  """yaml
6
6
  exposition:
7
7
  /:
8
+ io:output: true
8
9
  POST: create
9
10
  /:id:
10
11
  GET: observe
@@ -22,6 +22,7 @@ Feature: Basic authentication
22
22
  """yaml
23
23
  exposition:
24
24
  /:
25
+ io:output: true
25
26
  anonymous: true # checking compatibility with anonymous access
26
27
  POST:
27
28
  incept: id
@@ -72,6 +73,7 @@ Feature: Basic authentication
72
73
  Given the annotation:
73
74
  """yaml
74
75
  /:
76
+ io:output: true
75
77
  /:id:
76
78
  id: id
77
79
  GET:
@@ -115,6 +117,25 @@ Feature: Basic authentication
115
117
  200 OK
116
118
  """
117
119
 
120
+ Scenario: Changing other identity the password
121
+ Given the `identity.basic` database contains:
122
+ | _id | username | password | _version |
123
+ | efe3a65ebbee47ed95a73edd911ea328 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O | 1 |
124
+ | 6c0be50cbfb043acafe69cc7d3895f84 | attacker | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O | 1 |
125
+ When the following request is received:
126
+ """
127
+ PATCH /identity/basic/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
128
+ authorization: Basic YXR0YWNrZXI6c2VjcmV0
129
+ accept: application/yaml
130
+ content-type: application/yaml
131
+
132
+ password: new-secret
133
+ """
134
+ Then the following reply is sent:
135
+ """
136
+ 403 Forbidden
137
+ """
138
+
118
139
  Scenario Outline: <problem> not meeting the requirements
119
140
  When the following request is received:
120
141
  """
@@ -173,6 +194,7 @@ Feature: Basic authentication
173
194
  And the annotation:
174
195
  """yaml
175
196
  /:
197
+ io:output: true
176
198
  GET:
177
199
  auth:role: system:stub
178
200
  dev:stub:
@@ -244,6 +266,7 @@ Feature: Basic authentication
244
266
  """yaml
245
267
  exposition:
246
268
  /:
269
+ io:output: true
247
270
  anonymous: true
248
271
  POST:
249
272
  incept: id
@@ -4,7 +4,6 @@ Feature: Identity Federation
4
4
  Given the `identity.federation` database is empty
5
5
  Given local IDP is running
6
6
 
7
-
8
7
  Scenario: Getting identity for a new user
9
8
  Given the `identity.federation` configuration:
10
9
  """yaml
@@ -27,9 +26,8 @@ Feature: Identity Federation
27
26
 
28
27
  id: ${{ User.id }}
29
28
  roles: []
30
- scheme: bearer
31
29
  """
32
- # validate token
30
+ # validate TOKEN
33
31
  When the following request is received:
34
32
  """
35
33
  GET /identity/ HTTP/1.1
@@ -41,7 +39,7 @@ Feature: Identity Federation
41
39
  200 OK
42
40
  id: ${{ User.id }}
43
41
  """
44
- # ensuring identity idemptotency
42
+ # ensuring identity idempotency
45
43
  When the following request is received:
46
44
  """
47
45
  GET /identity/ HTTP/1.1
@@ -81,7 +79,6 @@ Feature: Identity Federation
81
79
  authorization: Token ${{ GoodUser.token }}
82
80
 
83
81
  id: ${{ GoodUser.id }}
84
- scheme: bearer
85
82
  """
86
83
 
87
84
  Scenario: Creating an Identity using inception with existing credentials
@@ -96,6 +93,7 @@ Feature: Identity Federation
96
93
  /:
97
94
  anonymous: true
98
95
  POST:
96
+ io:output: true
99
97
  incept: id
100
98
  endpoint: create
101
99
  """
@@ -11,6 +11,7 @@ Feature: Roles management
11
11
  And the annotation:
12
12
  """yaml
13
13
  /:
14
+ io:output: true
14
15
  auth:role: test
15
16
  GET:
16
17
  dev:stub:
@@ -7,6 +7,7 @@ Feature: Tokens lifecycle
7
7
  Given the annotation:
8
8
  """yaml
9
9
  /:
10
+ io:output: true
10
11
  /hello/:id:
11
12
  auth:id: id
12
13
  GET:
@@ -35,6 +36,7 @@ Feature: Tokens lifecycle
35
36
  And the annotation:
36
37
  """yaml
37
38
  /:
39
+ io:output: true
38
40
  /hello/:id:
39
41
  auth:id: id
40
42
  GET:
@@ -72,6 +74,7 @@ Feature: Tokens lifecycle
72
74
  Given the annotation:
73
75
  """yaml
74
76
  /:
77
+ io:output: true
75
78
  /:id:
76
79
  id: id
77
80
  GET: