github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/docs/registry.md (about) 1 [Table of contents](README.md#table-of-contents) 2 3 # Apps registry 4 5 The apps registry is a place where developers can submit their applications, 6 both web apps and konnectors. The applications metadata are stored and 7 versioned. It can be used by a cozy to list applications to be installed, and 8 for auto-updating the applications. 9 10 We define the applications registry as an API. This should allow us to defer the 11 real implementation of the registry storage and allow different store 12 implementations. 13 14 The stack itself implement the 15 [querying part of the registry API](#apis-querying-registry), proxying the 16 request to 17 [the registries attached to the instance](#attaching-a-cozy-stack-to-a-registry-or-a-list-of-registries). 18 19 ## Publishing on our official registries 20 21 In order for you to publish on our official registries, please follow 22 [this howto](./registry-publish.md) describing how to obtain a token and 23 parameter you repository to automatically publish versions. 24 25 ## Channels 26 27 We differentiate three channels of release for each application: 28 29 - stable: for stable releases 30 - beta: for application that can be tested in advance 31 - dev: for the latest releases directly from the trunk of the repository 32 33 For each of these channels, the version string has a different format which 34 differentiate the version channel: 35 36 - stable: `X.Y.Z` where `X`, `Y` and `Z` are positive or null integers. 37 - beta: `X.Y.Z-beta.M` where `X`, `Y`, `Z` and `M` are positive or null 38 integers 39 - dev: `X.Y.Z-dev.checksum` where `X`, `Y` and `Z` are positive or null 40 integers and `checksum` is a unique identifier of the dev release (typically 41 a shasum of the git commit) 42 43 ## Version order 44 45 TLDR: `1.0.0-dev._ < 1.0.0` and `1.0.0-beta._ < 1.0.0`, make sure you upgrade 46 your app version after publishing stable. 47 48 The order used to determine the latest version of a channel is the following: 49 50 - `1.0.0-dev.* < 1.0.0 (dev < stable)` 51 - `1.0.0-beta.* < 1.0.0 (beta < stable)` 52 - `1.0.0-beta.1 < 1.0.0-beta.2` 53 54 To order beta and dev releases, we apply a sort by their creation date. 55 56 ## Objects 57 58 Two types of objects are managed in the registry: applications and versions. 59 60 ### Application 61 62 An application described a specific package. It is linked to multiple versions 63 (releases) of the application. 64 65 An application object is **mutable**. 66 67 An application object contains the following fields: 68 69 - `slug`: the application slug (unique) 70 - `type`: the application type ("webapp" or "konnector") 71 - `editor`: the application editor name 72 - `versions`: an object containing all the channels versions 73 - `latest_version`: the latest available version 74 - `maintenance_activated`: boolean, true when the maintenance mode is 75 activated on the application 76 - `maintenance_options`: present only if `maintenance_activated` is true, 77 object with the following fields: 78 - `flag_infra_maintenance`: bool, true iff the maintenance is internal to 79 the cozy infrastructure 80 - `flag_short_maintenance`: bool, true iff the maintenance is a short 81 maintenance, waiting for a correction on our side 82 - `flag_disallow_manual_exec`: bool, true iff the maintenance will 83 disallow the execution on the application, even when manually executed 84 - `messages`: a list of localized messages containing a short and long 85 information messages explaining the maintenance state 86 - `label`: integer for a confidence grade from 0 to 5 (A to F), labelling the 87 application from a user privacy standpoint. It is calculated from the 88 `data_usage_commitment` and `data_usage_commitment_by` fields. 89 - `data_usage_commitment`: specify a technical commitment from the application 90 editor: 91 - `user_ciphered`: technical commitment that the user's data is encrypted 92 and can only be known by him. 93 - `user_reserved`: commitment that the data is only used for the user, to 94 directly offer its service. 95 - `none`: no commitment 96 - `data_usage_commitment_by`: specify what entity is taking the commitment: 97 - `cozy`: the commitment is taken by cozy 98 - `editor`: the commitment is taken by the application's editor 99 - `none`: no commitment is taken 100 101 Example: 102 103 ```json 104 { 105 "slug": "drive", 106 "type": "webapp", 107 "editor": "cozy", 108 "versions": { 109 "stable": ["3.1.1"], 110 "beta": ["3.1.1-beta.1"], 111 "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"] 112 }, 113 "latest_version": { 114 /* */ 115 } 116 } 117 ``` 118 119 ### Version 120 121 A version object describe a specific release of an application. 122 123 A version object is **immutable**. 124 125 An application version object contains the following fields: 126 127 - `slug`: the application slug 128 - `type`: the application type (webapp, konnector, ...) 129 - `manifest`: the [entire](./apps.md#the-manifest) 130 [manifest](./konnectors.md#the-manifest) defined in the package 131 - `created_at`: date of the release creation 132 - `url`: URL of the tarball containing the application at specified version 133 - `size`: the size of the application package (uncompressed) in bytes as 134 string 135 - `sha256`: the sha256 checksum of the application content 136 - `tar_prefix`: optional tar prefix directory specified to properly extract 137 the application content 138 139 The version string should follow the channels rule. 140 141 Example: 142 143 ```json 144 { 145 "slug": "drive", 146 "type": "webapp", 147 "version": "3.1.2", 148 "created_at": "2017-07-05T07:54:40.982Z", 149 "url": "http://.../3.1.2", 150 "size": "1000", 151 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 152 "manifest": { 153 /* ... */ 154 }, 155 "maintenance_activated": true, 156 "maintenance_options": { 157 "flag_infra_maintenance": true, 158 "flag_short_maintenance": false, 159 "flag_disallow_manual_exec": true, 160 "messages": { 161 "en": { 162 "long_message": "The app is currently in maintenance because of ....", 163 "short_message": "The app is currently in maintenance" 164 }, 165 "fr": { 166 "long_message": "L'application est en cours de maintenance à cause de ...", 167 "short_message": "L'application est en cours de maintenance" 168 } 169 } 170 } 171 } 172 ``` 173 174 ## APIs: Adding to registry 175 176 These APIs can be used to add elements to the registry. 177 178 ### POST /registry 179 180 This route register or modify an application to the registry. 181 The content of the request should be a json object of an application. 182 183 #### Status codes 184 185 - 201 Created, when the application has been successfully added 186 - 409 Conflict, when an application with the same slug already exists 187 - 400 Bad request, if the given application data is malformed (bad slug, 188 missing editor, ...) 189 190 #### Request 191 192 ```http 193 POST /registry HTTP/1.1 194 Authorization: Token AbCdE 195 ``` 196 197 ```json 198 { 199 "slug": "drive", 200 "editor": "cozy", 201 "name": { 202 "en": "Drive", 203 "fr": "Drive" 204 }, 205 "description": { 206 "en": "The drive application" 207 }, 208 "repository": "https://github.com/cozy/cozy-drive" 209 } 210 ``` 211 212 ### POST /registry/:app 213 214 This route adds a version of an already registered application to the 215 registry to the specified channel (stable, beta or dev). 216 217 The content of the manifest file extracted from the application data is used to 218 fill the fields of the version. Before adding the application version to the 219 registry, the registry should check the following: 220 221 - the `manifest` file contained in the tarball should be checked and have its 222 fields checked against the application properties 223 - the application content should check the sha256 checksum 224 225 Fields of the object sent to this request: 226 227 - **`url`**: the url where the application tarball is stored 228 - **`sha256`**: the sha256 checksum of the tarball 229 - **`version`**: the version value (should match the one in the manifest) 230 - `parameters?`: an optional json value (any) that will override the 231 `parameters` field of the manifest 232 - `icon?`: an optional path to override the `icon` field of the manifest 233 - `screenshots?`: and optional array of path to override the `screenshots` 234 field of the manifest 235 236 #### Status codes 237 238 - 201 Created, when the version has been successfully added to the registry 239 - 409 Conflict, when the version already exists 240 - 404 Not Found, when the application does not exist 241 - 412 Precondition Failed, when the sent application data is invalid (could 242 not fetch data URL, bad checksum, bad manifest in the tarball...) 243 - 400 Bad request, when the request is invalid (bad checksum encoding, bad 244 URL...) 245 246 #### Request 247 248 Request to add a stable release: 249 250 ```http 251 POST /registry/drive HTTP/1.1 252 Authorization: Token AbCdE 253 ``` 254 255 ```json 256 { 257 "version": "3.1.2", 258 "url": "https://github.com/cozy/cozy-drive/archive/v3.1.2.tar.gz", 259 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f" 260 } 261 ``` 262 263 Request to add a development release: 264 265 ```http 266 POST /registry/drive HTTP/1.1 267 Authorization: Token AbCdE 268 ``` 269 270 ```json 271 { 272 "version": "3.1.2-dev.7a1618dff78ba445650f266bbe334cbc9176f03a", 273 "url": "https://github.com/cozy/cozy-photos-v3/archive/7a1618dff78ba445650f266bbe334cbc9176f03a.zip", 274 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f" 275 } 276 ``` 277 278 Request to add a version with optional parameters: 279 280 ```http 281 POST /registry/drive HTTP/1.1 282 Authorization: Token AbCdE 283 ``` 284 285 ```json 286 { 287 "version": "3.1.2", 288 "url": "https://github.com/cozy/cozy-photos-v3/archive/7a1618dff78ba445650f266bbe334cbc9176f03a.zip", 289 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 290 "parameters": { "foo": "bar", "baz": 123 } 291 } 292 ``` 293 294 #### Response 295 296 ```http 297 HTTP/1.1 201 Created 298 Content-Type: application/json 299 Location: http://.../3.1.2 300 ``` 301 302 ```json 303 { 304 "slug": "drive", 305 "type": "webapp", 306 "version": "3.1.2-dev.7a1618dff78ba445650f266bbe334cbc9176f03a", 307 "created_at": "2017-07-05T07:54:40.982Z", 308 "url": "http://.../7a1618dff78ba445650f266bbe334cbc9176f03a.zip", 309 "size": "1000", 310 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 311 "manifest": { 312 /* ... */ 313 } 314 } 315 ``` 316 317 ## APIs: Querying registry 318 319 These routes define the querying part of a registry to access to the available 320 applications and versions. These APIs are also implemented directly by the 321 cozy-stack. 322 323 ### GET /registry 324 325 Get the list of all applications. 326 327 A pagination scheme is available via the `limit` and `cursor` query parameter. 328 The `filter[???]` query parameters can be used to filter by fields values. 329 330 Filtering is allowed on the following fields: 331 332 - `type` 333 - `editor` 334 335 Sorting is allowed on the following fields: 336 337 - `slug` 338 - `type` 339 - `editor` 340 - `created_at` 341 342 #### Query-String 343 344 | Parameter | Description | 345 | -------------------- | -------------------------------------------------------- | 346 | cursor | the cursor of the last application on the previous page | 347 | limit | the maximum number of applications to show | 348 | filter[] | a filter to apply on fields of the application | 349 | sort | name of the field on which to apply the sort of the list | 350 | versionsChannel | the channels from which we list the version numbers | 351 | latestChannelVersion | the channel from which we select the latest version | 352 353 #### Request 354 355 ```http 356 GET /registry?filter[category]=main&limit=20&sort=slug&versionsChannel=dev&latestChannelVersion=beta HTTP/1.1 357 ``` 358 359 #### Response 360 361 ```http 362 HTTP/1.1 200 OK 363 Content-Type: application/json 364 ``` 365 366 ```json 367 { 368 "data": [ 369 { 370 "slug": "drive", 371 "type": "webapp", 372 "editor": "cozy", 373 "versions": { 374 "stable": ["3.1.1"], 375 "beta": ["3.1.1-beta.1"], 376 "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"] 377 }, 378 "latest_version": { 379 "slug": "drive", 380 "type": "webapp", 381 "version": "3.1.1-beta.1", 382 "url": "http://.../3.1.1-beta.1", 383 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 384 "size": "1000", 385 "created_at": "2017-07-05T07:54:40.982Z", 386 "manifest": { 387 /* ... */ 388 } 389 } 390 }, 391 { 392 // ... 393 } 394 ], 395 "meta": { 396 "count": 2, 397 "next_cursor": "..." 398 } 399 } 400 ``` 401 402 ### GET /registry/:app 403 404 Get an application object by slug. 405 406 #### Request 407 408 ```http 409 GET /registry/drive HTTP/1.1 410 ``` 411 412 #### Response 413 414 ```http 415 HTTP/1.1 200 OK 416 Content-Type: application/json 417 ``` 418 419 ```json 420 { 421 "slug": "drive", 422 "editor": "cozy", 423 "latest_version": { 424 "slug": "drive", 425 "type": "webapp", 426 "version": "3.1.1", 427 "url": "http://.../3.1.1", 428 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 429 "size": "1000", 430 "created_at": "2017-07-05T07:54:40.982Z", 431 "manifest": { 432 /* ... */ 433 } 434 }, 435 "versions": { 436 "stable": ["3.1.1"], 437 "beta": ["3.1.1-beta.1"], 438 "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"] 439 } 440 } 441 ``` 442 443 ### GET /registry/:app/icon 444 445 Get the current application icon. 446 447 #### Request 448 449 ```http 450 GET /registry/drive/icon HTTP/1.1 451 ``` 452 453 #### Response 454 455 ```http 456 HTTP/1.1 200 OK 457 Content-Type: image/svg+xml 458 459 <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> 460 <g fill="none" fill-rule="evenodd"></g> 461 </svg> 462 ``` 463 464 ### GET /registry/:app/partnership_icon 465 466 Get the current application partnership_icon. 467 468 #### Request 469 470 ```http 471 GET /registry/drive/partnership_icon HTTP/1.1 472 ``` 473 474 #### Response 475 476 ```http 477 HTTP/1.1 200 OK 478 Content-Type: image/svg+xml 479 480 <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> 481 <g fill="none" fill-rule="evenodd"></g> 482 </svg> 483 ``` 484 485 ### GET /registry/:app/screenshots/:filename 486 487 Get the screenshot with the specified filename from the field `screenshots` of 488 the application. 489 490 #### Request 491 492 ```http 493 GET /registry/drive/screenshots/screen1.jpg HTTP/1.1 494 ``` 495 496 #### Response 497 498 ```http 499 HTTP/1.1 200 OK 500 Content-Type: image/jpeg 501 502 ... 503 ``` 504 505 ### GET /registry/:app/:version 506 507 Get an application version. 508 509 #### Request 510 511 ```http 512 GET /registry/drive/3.1.1 HTTP/1.1 513 ``` 514 515 #### Response 516 517 ```http 518 HTTP/1.1 200 OK 519 Content-Type: application/json 520 ``` 521 522 ```json 523 { 524 "slug": "drive", 525 "type": "webapp", 526 "version": "3.1.1", 527 "url": "http://.../3.1.1", 528 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 529 "size": "1000", 530 "created_at": "2017-07-05T07:54:40.982Z", 531 "manifest": { 532 /* ... */ 533 } 534 } 535 ``` 536 537 ### GET /registry/:app/:channel/latest 538 539 Get the latest version available on the specified channel. 540 541 #### Request 542 543 ```http 544 GET /registry/drive/dev/latest HTTP/1.1 545 ``` 546 547 #### Response 548 549 ```http 550 HTTP/1.1 200 OK 551 Content-Type: application/json 552 ``` 553 554 ```json 555 { 556 "slug": "drive", 557 "type": "webapp", 558 "version": "3.1.1", 559 "url": "http://.../3.1.1", 560 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 561 "size": "1000", 562 "created_at": "2017-07-05T07:54:40.982Z", 563 "manifest": { 564 /* ... */ 565 } 566 } 567 ``` 568 569 ### GET /registry/maintenance 570 571 Get the list of applications (and konnectors) with maintenance mode activated. 572 573 #### Request 574 575 ```http 576 GET /registry/maintenance HTTP/1.1 577 ``` 578 579 #### Response 580 581 ```http 582 HTTP/1.1 200 OK 583 Content-Type: application/json 584 ``` 585 586 ```json 587 [ 588 { 589 "slug": "drive", 590 "type": "webapp", 591 "version": "3.1.1", 592 "url": "http://.../3.1.1", 593 "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f", 594 "size": "1000", 595 "created_at": "2017-07-05T07:54:40.982Z", 596 "manifest": { 597 /* ... */ 598 }, 599 "maintenance_activated": true, 600 "maintenance_options": { 601 "flag_infra_maintenance": true, 602 "flag_short_maintenance": false, 603 "flag_disallow_manual_exec": true 604 } 605 } 606 ] 607 ``` 608 609 ## Attaching a cozy-stack to a registry or a list of registries 610 611 In the configuration file of a stack, a `registries` namespace is added. This 612 namespace can contain a list of URL for the different registries attached to the 613 stack. 614 615 The stack itself implements the querying API of a registry. When querying this 616 API, to ask for an application, the stack uses this hierarchy of registries to 617 proxy or redirect the user. 618 619 The hierarchy can also be contextualised to specify different registries to 620 different contexts. The `default` context is applied lastly. 621 622 ### Examples: 623 624 ```yaml 625 registries: 626 - https://myregistry.home/ 627 - https://main.registry.cozy.io/ 628 ``` 629 630 ```yaml 631 # In this example, a "context1" instance will have the equivalent of the 632 # following list of registries: 633 # 634 # - https://context1.registry.cozy.io/ 635 # - https://myregistry.home/ 636 # - https://registry.cozy.io/ 637 # 638 639 registries: 640 context1: 641 - https://context1.registry.cozy.io/ 642 643 context2: 644 - https://context2.registry.cozy.io/ 645 646 default: 647 - https://myregistry.home/ 648 - https://registry.cozy.io/ 649 ``` 650 651 # Authentication 652 653 The authentication is based on a token that allow you to publish applications 654 and versions with for one specific editor name. This token is base64 encoded. 655 656 In order to receive this token, please take a look at the page on 657 [publication on the registry](./registry-publish.md).