aboutsummaryrefslogtreecommitdiffstats
path: root/src/devtools/spec-afbidl.md
blob: 74256659588067bf3da1482e7d190df234816ff5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
API specification for AGL
=========================

Micro service architectures on web mostly use OpenAPI
for specifying and documenting their API (Application
Programming Interface).
Following that use, AGL's binder provides a tool to
translate OpenAPI specifications to a code skeleton
written either in C or C++ languages.

However, the API descritpion language OpenAPI never
provided some the requirement that AGL expected for
a such tool:

 - specify API that throws events
 - describe the permission based security model

Using OpenAPI also had the disavantage of implying
some twist of the model and then some uglyness
verbosity.

Unfortunately, search for a replacement of OpenAPI
that would fullfil below requirements failed.

 - Describe JSON data of APIs
 - Describe events
 - Describe permission based security (even as extension)
 - Suitable for generating:
    * Documentation
    * Code skeleton with/without parameter validation
    * Automated test

Consequently, a new API specification formalism has
to be proposed.

This document is the proposal for that new formalism.
For the best, that proposal includes advanced designs
introduced after discussions with Joël Champeau and
Philippe Dhaussy, researchers at ENSTA Bretagne (National
Institute of Advanced Technologies of Brittany) specialized
in system modeling and formal verification.


The goals of specifying APIs
----------------------------

The micro service architecture of AGL and its flexible
IPC mechanism emphasis the decomposition of services or
applications in tiny cooperative parts.
This has big advantages in terms of flexibility and
development process but, conversely, implies to
correctly document interfaces.
Documenting or specifying API are the same thing, except
that, traditionnaly, specifying comes forward and
documenting afterward.

Specifying API can be done using simple text documents.
Using text documents is great for humans but not for
computers.
For this reason, because machines can't exploit human
structured texts, the use of simple text documents
should be avoided as much as possible.
In effect, here is the list of all items that computers
can do based on API specifications:

 - Automatic generation of documentation
   in many formats and using customizable styles

 - Automatic generation of code either
   minimal or elaborate

 - Automatic adaptation to tansport backend or
   protocol

 - Automatic generation of test cases

 - Integration of advanced tools like supervision,
   tracing, spying

 - Proof of system properties, in particular
   when assembling many API together

Many IDL (Interface Description Language) exist
but it rarely fit all that requirements.
First of all, they generally are "languages",
meaning that they are difficult to parse, to
generate and to manipulate by tools.

OpenAPI is not a language. It is a specification
made by a data structure of JSON format [1][json-org],
[2][json-rfc].
Using JSON has the advantage that no parser has
to be written because a standard one exists.
JSON is not human friendly but its data model
is quasi-isomorph with the one of YAML [3][yaml]
that is more human friendly.

For this reasons, the below proposal describes
an API specification format based on YAML.

Nevertheless, for specifying the values expected
by APIs the format will use the JSON Schema formalism
[4][json-schema]. This allows to describe complex
values and their constraints using a format easy to
integrate in tools.

[json-org]:    http://json.org/                    "JSON format"
[json-rfc]:    https://tools.ietf.org/html/rfc8259 "JSON format RFC"
[yaml]:        https://yaml.org/                   "YAML format"
[json-schema]: https://json-schema.org/            "JSON Schema"

Content of API specifications
-----------------------------

### Top level structure

An API specification has the following structure:

```yaml
%YAML 1.3
---
afbidl: "0.1"
info: # description the content of the specification
tools: # items for tools (doc, afb-genskel, ..)
verbs: # description of verbs of the API
events: # description of the events emitted by the API
state-machines: # description of the state machines of the API
examples: # examples of usage with or without timings
schemas: # place holder for description of the types of items
```

The specification is designed to describe only one API.
If needed (example: simulation of a complex system), the aggregation
of multiple API descriptions can be done but externally with some
other description.

The heading line *%YAML 1.3* is recommended but not mandatory.

The main item of the description is an object. Its fields are:

 - afbidl: this field indicates that the description follows that
   specification and the value precise what version of the specification
   is used. Current version is 0.1

 - info: this field contains an object that give informations about the
   API. Its mandatory fields are:

      - apiname: name of the API
      - title: short explanation of the API
      - description: long description of the API
      - version: version of the API

   Other fields are accepted, example: author, maintainer, homepage,
   site, copyright, license, ...

 - tools: this fields contains an object that can set properties for
   processing tools. The fields are the names of tool to setup.

 - verbs: this field contains an object whose fields are the names
   of the verbs of the API. For each verb the value attached to the
   field of the verb is the description of the verb.

 - events: this field contains an object whose fields are the names
   of the events thrown by the API. For each event the value attached
   to the field describes the event.

 - state-machines: this field contains an object whose fields are the
   names of the state-machines of the API. For each state-machine the
   value attached to the field describes the state machine.

 - examples: TO BE SPECIFIED - object of named sequences/scenarii -

 - schemas: this optionnal field is intended to group the schema of
   the common types used by API.


### Describing verbs

The verbs are described using an object containing the fields

```yaml
title: # short explanation of the verb
description: # detailed description of the verb
permissions: # required permissions
request: # schema of the request parameters
reply: # describe the reply
```

### Describing events

The events are described using an object containing the fields

```yaml
schema: # description of the data associated with the event
when-state: # condition of emiting the event
set-state: # when the event is associated to a state change
```

### Describing state machine




Example of the API gps
----------------------

```yaml
%YAML 1.3
---
afbidl: "0.1"

info:
  apiname: gps
  title: Service for geolocation
  description:
        GPS service reports current WGS84 coordinates from GNSS devices
        via the gpsd application.
  version: "0.1"
  author: AGL
  maintainer: John Difool
  homepage: https://doc.automotivelinux.org/...

tools:

    afb-genskel:
        scope: static
        prefix: req_
        postfix: _cb
        init: init_gps

    doc:
        id: gps-api
        keywords: gps
        author:
        version:
        src_prefix: api-gps
        chapters:
        - name: Abstract
          url: abstract.md
        - name: User Guide
          url: userguide.md

verbs:

    subscribe:
        description: subscribe to gps/gnss events
        request: $/schemas/subscription-desc
        reply:
            success:
                schema: $/schemas/none
                set-state:
                    listening: yes

    unsubscribe:
        description: unsubscribe to gps/gnss events
        request: $/schemas/subscription-desc
        reply:
            success:
                schema: $/schemas/none
                set-state:
                    listening: no

    location:
        description: get current gps/gnss coordinates
        request: $/schemas/none
        reply:
            success: $/schemas/location
            _: An error can be returned when the service isn't ready

    record:
        description: |
            Entering *record* mode you must send **{"state": "on"}** with the **record**
            verb which will have a JSON response of **{"filename": "gps_YYYYMMDD_hhmm.log"}**
            pointing to log under *app-data/agl-service-gps*

            Now to enter *replaying* mode you must symlink or copy a GPS dump to
            *app-data/agl-service-gps/recording.log* and restart the service.
            From then on out the previously recorded GPS data will loop infinitely
            which is useful for testing or demonstration purposes.
        request: $/schemas/record/request
        reply:
            success:
                schema: $/schemas/record/reply
                set-state:
                    recording: yes
            _: An error can be returned when the service isn't ready

events:
    location:
        schema: $/schemas/location
        when-state:
            listening: yes

state-machines:
    listening:
        states: [ no, yes ]
        initial: no
    recording:
        states: [ no, yes ]
        initial: no

# Follow JsonSchema specification (https://json-schema.org/)
schemas:
    subscription-desc:
        title: Description of the event subscribed or unsubscribed
        type: object
        properties:
            value: { enum: [ location ] }
        required: [ value ]

    location:
        title: the location
        type: object
        properties:
            altitude:
                title: the altitude in meters above the normal geoide
                type: number
                minimum: -20000
                maximum: 20000
            latitude:
                title: the latitude in degrees
                type: number
                minimum: -90
                maximum: 90
            longitude:
                title: the longitude in degrees
                type: number
                minimum: -180
                maximum: 180
            speed:
                title: the speed in meter per seconds m/s
                type: number
                minimum: 0
                maximum: 6000
            track:
                title: the heading in degrees
                type: number
                minimum: 0
                maximum: 360
            timestamp:
                title: time stamp of the location as a ISO8601 date
                type: string #ISO8601
                pattern: \d{4,}-[01][0-9]-[0-3][0-9]T[012][0-9]:[0-5][0-9]:[0-5][0-9].*

    record:
        request:
            type: object
            properties:
                state: { const: "on" }
            required: [ state ]

        reply:
            type: object
            properties:
                filename:
                    title: the name of the file that records the data of format gps_YYYYMMDD_hhmm.log
                    type: string
                    pattern: gps_\d{4}\d{2}\d{2}_\d{2}\d{2}.log
            required: [ filename ]

    none:
        title: no value, just null
        const: null
```