wip
[src/app-framework-binder.git] / src / devtools / spec-afbidl.md
1 API specification for AGL
2 =========================
3
4 Micro service architectures on web mostly use OpenAPI
5 for specifying and documenting their API (Application
6 Programming Interface).
7 Following that use, AGL's binder provides a tool to
8 translate OpenAPI specifications to a code skeleton
9 written either in C or C++ languages.
10
11 However, the API descritpion language OpenAPI never
12 provided some the requirement that AGL expected for
13 a such tool:
14
15  - specify API that throws events
16  - describe the permission based security model
17
18 Using OpenAPI also had the disavantage of implying
19 some twist of the model and then some uglyness
20 verbosity.
21
22 Unfortunately, search for a replacement of OpenAPI
23 that would fullfil below requirements failed.
24
25  - Describe JSON data of APIs
26  - Describe events
27  - Describe permission based security (even as extension)
28  - Suitable for generating:
29     * Documentation
30     * Code skeleton with/without parameter validation
31     * Automated test
32
33 Consequently, a new API specification formalism has
34 to be proposed.
35
36 This document is the proposal for that new formalism.
37 For the best, that proposal includes advanced designs
38 introduced after discussions with Joël Champeau and
39 Philippe Dhaussy, researchers at ENSTA Bretagne (National
40 Institute of Advanced Technologies of Brittany) specialized
41 in system modeling and formal verification.
42
43
44 The goals of specifying APIs
45 ----------------------------
46
47 The micro service architecture of AGL and its flexible
48 IPC mechanism emphasis the decomposition of services or
49 applications in tiny cooperative parts.
50 This has big advantages in terms of flexibility and
51 development process but, conversely, implies to
52 correctly document interfaces.
53 Documenting or specifying API are the same thing, except
54 that, traditionnaly, specifying comes forward and
55 documenting afterward.
56
57 Specifying API can be done using simple text documents.
58 Using text documents is great for humans but not for
59 computers.
60 For this reason, because machines can't exploit human
61 structured texts, the use of simple text documents
62 should be avoided as much as possible.
63 In effect, here is the list of all items that computers
64 can do based on API specifications:
65
66  - Automatic generation of documentation
67    in many formats and using customizable styles
68
69  - Automatic generation of code either
70    minimal or elaborate
71
72  - Automatic adaptation to tansport backend or
73    protocol
74
75  - Automatic generation of test cases
76
77  - Integration of advanced tools like supervision,
78    tracing, spying
79
80  - Proof of system properties, in particular
81    when assembling many API together
82
83 Many IDL (Interface Description Language) exist
84 but it rarely fit all that requirements.
85 First of all, they generally are "languages",
86 meaning that they are difficult to parse, to
87 generate and to manipulate by tools.
88
89 OpenAPI is not a language. It is a specification
90 made by a data structure of JSON format [1][json-org],
91 [2][json-rfc].
92 Using JSON has the advantage that no parser has
93 to be written because a standard one exists.
94 JSON is not human friendly but its data model
95 is quasi-isomorph with the one of YAML [3][yaml]
96 that is more human friendly.
97
98 For this reasons, the below proposal describes
99 an API specification format based on YAML.
100
101 Nevertheless, for specifying the values expected
102 by APIs the format will use the JSON Schema formalism
103 [4][json-schema]. This allows to describe complex
104 values and their constraints using a format easy to
105 integrate in tools.
106
107 [json-org]:    http://json.org/                    "JSON format"
108 [json-rfc]:    https://tools.ietf.org/html/rfc8259 "JSON format RFC"
109 [yaml]:        https://yaml.org/                   "YAML format"
110 [json-schema]: https://json-schema.org/            "JSON Schema"
111
112 Content of API specifications
113 -----------------------------
114
115 ### Top level structure
116
117 An API specification has the following structure:
118
119 ```yaml
120 %YAML 1.3
121 ---
122 afbidl: "0.1"
123 info: # description the content of the specification
124 tools: # items for tools (doc, afb-genskel, ..)
125 verbs: # description of verbs of the API
126 events: # description of the events emitted by the API
127 state-machines: # description of the state machines of the API
128 examples: # examples of usage with or without timings
129 schemas: # place holder for description of the types of items
130 ```
131
132 The specification is designed to describe only one API.
133 If needed (example: simulation of a complex system), the aggregation
134 of multiple API descriptions can be done but externally with some
135 other description.
136
137 The heading line *%YAML 1.3* is recommended but not mandatory.
138
139 The main item of the description is an object. Its fields are:
140
141  - afbidl: this field indicates that the description follows that
142    specification and the value precise what version of the specification
143    is used. Current version is 0.1
144
145  - info: this field contains an object that give informations about the
146    API. Its mandatory fields are:
147
148       - apiname: name of the API
149       - title: short explanation of the API
150       - description: long description of the API
151       - version: version of the API
152
153    Other fields are accepted, example: author, maintainer, homepage,
154    site, copyright, license, ...
155
156  - tools: this fields contains an object that can set properties for
157    processing tools. The fields are the names of tool to setup.
158
159  - verbs: this field contains an object whose fields are the names
160    of the verbs of the API. For each verb the value attached to the
161    field of the verb is the description of the verb.
162
163  - events: this field contains an object whose fields are the names
164    of the events thrown by the API. For each event the value attached
165    to the field describes the event.
166
167  - state-machines: this field contains an object whose fields are the
168    names of the state-machines of the API. For each state-machine the
169    value attached to the field describes the state machine.
170
171  - examples: TO BE SPECIFIED - object of named sequences/scenarii -
172
173  - schemas: this optionnal field is intended to group the schema of
174    the common types used by API.
175
176
177 ### Describing verbs
178
179 The verbs are described using an object containing the fields
180
181 ```yaml
182 title: # short explanation of the verb
183 description: # detailed description of the verb
184 permissions: # required permissions
185 request: # schema of the request parameters
186 reply: # describe the reply
187 ```
188
189 ### Describing events
190
191 The events are described using an object containing the fields
192
193 ```yaml
194 schema: # description of the data associated with the event
195 when-state: # condition of emiting the event
196 set-state: # when the event is associated to a state change
197 ```
198
199 ### Describing state machine
200
201
202
203
204 Example of the API gps
205 ----------------------
206
207 ```yaml
208 %YAML 1.3
209 ---
210 afbidl: "0.1"
211
212 info:
213   apiname: gps
214   title: Service for geolocation
215   description:
216         GPS service reports current WGS84 coordinates from GNSS devices
217         via the gpsd application.
218   version: "0.1"
219   author: AGL
220   maintainer: John Difool
221   homepage: https://doc.automotivelinux.org/...
222
223 tools:
224
225     afb-genskel:
226         scope: static
227         prefix: req_
228         postfix: _cb
229         init: init_gps
230
231     doc:
232         id: gps-api
233         keywords: gps
234         author:
235         version:
236         src_prefix: api-gps
237         chapters:
238         - name: Abstract
239           url: abstract.md
240         - name: User Guide
241           url: userguide.md
242
243 verbs:
244
245     subscribe:
246         description: subscribe to gps/gnss events
247         request: $/schemas/subscription-desc
248         reply:
249             success:
250                 schema: $/schemas/none
251                 set-state:
252                     listening: yes
253
254     unsubscribe:
255         description: unsubscribe to gps/gnss events
256         request: $/schemas/subscription-desc
257         reply:
258             success:
259                 schema: $/schemas/none
260                 set-state:
261                     listening: no
262
263     location:
264         description: get current gps/gnss coordinates
265         request: $/schemas/none
266         reply:
267             success: $/schemas/location
268             _: An error can be returned when the service isn't ready
269
270     record:
271         description: |
272             Entering *record* mode you must send **{"state": "on"}** with the **record**
273             verb which will have a JSON response of **{"filename": "gps_YYYYMMDD_hhmm.log"}**
274             pointing to log under *app-data/agl-service-gps*
275
276             Now to enter *replaying* mode you must symlink or copy a GPS dump to
277             *app-data/agl-service-gps/recording.log* and restart the service.
278             From then on out the previously recorded GPS data will loop infinitely
279             which is useful for testing or demonstration purposes.
280         request: $/schemas/record/request
281         reply:
282             success:
283                 schema: $/schemas/record/reply
284                 set-state:
285                     recording: yes
286             _: An error can be returned when the service isn't ready
287
288 events:
289     location:
290         schema: $/schemas/location
291         when-state:
292             listening: yes
293
294 state-machines:
295     listening:
296         states: [ no, yes ]
297         initial: no
298     recording:
299         states: [ no, yes ]
300         initial: no
301
302 # Follow JsonSchema specification (https://json-schema.org/)
303 schemas:
304     subscription-desc:
305         title: Description of the event subscribed or unsubscribed
306         type: object
307         properties:
308             value: { enum: [ location ] }
309         required: [ value ]
310
311     location:
312         title: the location
313         type: object
314         properties:
315             altitude:
316                 title: the altitude in meters above the normal geoide
317                 type: number
318                 minimum: -20000
319                 maximum: 20000
320             latitude:
321                 title: the latitude in degrees
322                 type: number
323                 minimum: -90
324                 maximum: 90
325             longitude:
326                 title: the longitude in degrees
327                 type: number
328                 minimum: -180
329                 maximum: 180
330             speed:
331                 title: the speed in meter per seconds m/s
332                 type: number
333                 minimum: 0
334                 maximum: 6000
335             track:
336                 title: the heading in degrees
337                 type: number
338                 minimum: 0
339                 maximum: 360
340             timestamp:
341                 title: time stamp of the location as a ISO8601 date
342                 type: string #ISO8601
343                 pattern: \d{4,}-[01][0-9]-[0-3][0-9]T[012][0-9]:[0-5][0-9]:[0-5][0-9].*
344
345     record:
346         request:
347             type: object
348             properties:
349                 state: { const: "on" }
350             required: [ state ]
351
352         reply:
353             type: object
354             properties:
355                 filename:
356                     title: the name of the file that records the data of format gps_YYYYMMDD_hhmm.log
357                     type: string
358                     pattern: gps_\d{4}\d{2}\d{2}_\d{2}\d{2}.log
359             required: [ filename ]
360
361     none:
362         title: no value, just null
363         const: null
364 ```
365