elemctl 0.45.0__tar.gz → 0.46.0__tar.gz

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 (79) hide show
  1. {elemctl-0.45.0 → elemctl-0.46.0}/PKG-INFO +14 -6
  2. {elemctl-0.45.0 → elemctl-0.46.0}/README.md +13 -5
  3. {elemctl-0.45.0 → elemctl-0.46.0}/docs/SPEC.md +72 -42
  4. {elemctl-0.45.0 → elemctl-0.46.0}/docs/SPEC.ru.md +160 -62
  5. {elemctl-0.45.0 → elemctl-0.46.0}/docs/changelog.md +60 -0
  6. {elemctl-0.45.0 → elemctl-0.46.0}/docs/changelog.ru.md +59 -0
  7. {elemctl-0.45.0 → elemctl-0.46.0}/docs/cli.md +24 -4
  8. {elemctl-0.45.0 → elemctl-0.46.0}/docs/cli.ru.md +24 -4
  9. {elemctl-0.45.0 → elemctl-0.46.0}/docs/config.md +9 -2
  10. {elemctl-0.45.0 → elemctl-0.46.0}/docs/config.ru.md +8 -2
  11. {elemctl-0.45.0 → elemctl-0.46.0}/docs/mcp.md +4 -3
  12. {elemctl-0.45.0 → elemctl-0.46.0}/docs/mcp.ru.md +7 -3
  13. {elemctl-0.45.0 → elemctl-0.46.0}/docs/platform.md +7 -6
  14. {elemctl-0.45.0 → elemctl-0.46.0}/docs/platform.ru.md +51 -12
  15. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/__init__.py +1 -1
  16. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/cli.py +32 -2
  17. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/client.py +104 -16
  18. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/deploy.py +185 -45
  19. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/i18n.py +160 -38
  20. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/mcp_server.py +53 -5
  21. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/probe.py +100 -28
  22. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/registry.py +110 -2
  23. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/schema.py +121 -14
  24. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/versions.py +62 -2
  25. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl.egg-info/PKG-INFO +14 -6
  26. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl.egg-info/SOURCES.txt +2 -0
  27. elemctl-0.46.0/tests/test_app_users.py +104 -0
  28. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_cli.py +19 -0
  29. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_client.py +67 -1
  30. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_deploy.py +331 -3
  31. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_i18n.py +3 -0
  32. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_mcp.py +44 -1
  33. elemctl-0.46.0/tests/test_numbering_jumps.py +184 -0
  34. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_probe_cleanup.py +109 -0
  35. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_registry.py +135 -0
  36. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_schema.py +189 -0
  37. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_versions.py +11 -0
  38. {elemctl-0.45.0 → elemctl-0.46.0}/.env.example +0 -0
  39. {elemctl-0.45.0 → elemctl-0.46.0}/LICENSE +0 -0
  40. {elemctl-0.45.0 → elemctl-0.46.0}/MANIFEST.in +0 -0
  41. {elemctl-0.45.0 → elemctl-0.46.0}/NOTICE +0 -0
  42. {elemctl-0.45.0 → elemctl-0.46.0}/ORIGIN.md +0 -0
  43. {elemctl-0.45.0 → elemctl-0.46.0}/docs/index.md +0 -0
  44. {elemctl-0.45.0 → elemctl-0.46.0}/docs/index.ru.md +0 -0
  45. {elemctl-0.45.0 → elemctl-0.46.0}/docs/library.md +0 -0
  46. {elemctl-0.45.0 → elemctl-0.46.0}/docs/library.ru.md +0 -0
  47. {elemctl-0.45.0 → elemctl-0.46.0}/pyproject.toml +0 -0
  48. {elemctl-0.45.0 → elemctl-0.46.0}/setup.cfg +0 -0
  49. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/__main__.py +0 -0
  50. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/auth.py +0 -0
  51. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/build.py +0 -0
  52. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/config.py +0 -0
  53. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/errors.py +0 -0
  54. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/plugins.py +0 -0
  55. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/selfupdate.py +0 -0
  56. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl/transport.py +0 -0
  57. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl.egg-info/dependency_links.txt +0 -0
  58. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl.egg-info/entry_points.txt +0 -0
  59. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl.egg-info/requires.txt +0 -0
  60. {elemctl-0.45.0 → elemctl-0.46.0}/src/elemctl.egg-info/top_level.txt +0 -0
  61. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_build.py +0 -0
  62. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_changelog_link.py +0 -0
  63. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_cli_docs.py +0 -0
  64. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_config.py +0 -0
  65. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_conventions.py +0 -0
  66. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_docs_coverage.py +0 -0
  67. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_extract_adapter.py +0 -0
  68. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_plugins.py +0 -0
  69. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_probe.py +0 -0
  70. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_rebuild_docs.py +0 -0
  71. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_release_notes.py +0 -0
  72. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_selfupdate.py +0 -0
  73. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_selfupdate_latest.py +0 -0
  74. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_server_starting.py +0 -0
  75. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_token_access.py +0 -0
  76. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_transport.py +0 -0
  77. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_user_lists.py +0 -0
  78. {elemctl-0.45.0 → elemctl-0.46.0}/tests/test_workflows.py +0 -0
  79. {elemctl-0.45.0 → elemctl-0.46.0}/tools/extract_adapter.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elemctl
3
- Version: 0.45.0
3
+ Version: 0.46.0
4
4
  Summary: CLI, MCP server and library for the Console API v2 of the 1C:Enterprise.Element platform (1cmycloud): applications, builds from source, one-command deploy with verification, a compile probe
5
5
  Author: KeyFire
6
6
  License-Expression: MIT
@@ -205,8 +205,8 @@ for the cache to watch and stays pinned for the life of the process instead.
205
205
 
206
206
  ### Behaviour of the tool
207
207
 
208
- `ELEMCTL_LANG`, `ELEMCTL_NO_PLUGINS` and `ELEMCTL_DATA_DIR` are set through the
209
- environment only – a connection `.env` is not their place. `ELEMCTL_NO_PROXY` is the
208
+ `ELEMCTL_LANG`, `ELEMCTL_NO_PLUGINS`, `ELEMCTL_DATA_DIR` and `ELEMCTL_REGISTRY_LIMIT` are
209
+ set through the environment only – a connection `.env` is not their place. `ELEMCTL_NO_PROXY` is the
210
210
  exception, explained above: it reads the same file the connection does.
211
211
 
212
212
  | Variable | Purpose |
@@ -215,6 +215,7 @@ exception, explained above: it reads the same file the connection does.
215
215
  | `ELEMCTL_NO_PROXY` | set it to bypass the environment's proxy for every call (loopback and private addresses are bypassed anyway); also readable from the stand's `.env` |
216
216
  | `ELEMCTL_NO_PLUGINS` | do not look for plugins: work with the core capabilities only |
217
217
  | `ELEMCTL_DATA_DIR` | the directory of the local registry of uploads; by default `%LOCALAPPDATA%\elemctl` on Windows and `$XDG_STATE_HOME/elemctl` (`~/.local/state/elemctl`) elsewhere |
218
+ | `ELEMCTL_REGISTRY_LIMIT` | how many uploads the local registry of uploads keeps; 1000 by default, `0` keeps every one |
218
219
 
219
220
  ### The local registry of uploads
220
221
 
@@ -231,6 +232,12 @@ had no registry yet is not in it, and there the listings show what the platform
231
232
  registry that cannot be written is a warning and never a failed upload; the file can be
232
233
  deleted at any time, and only the history of this machine goes with it.
233
234
 
235
+ The registry keeps the newest thousand uploads, `ELEMCTL_REGISTRY_LIMIT` sets another
236
+ number, and `0` keeps every one. Once the file has grown past the limit by a tenth, the next
237
+ upload cuts it back to the newest lines: the builds a project still lists and an application
238
+ still runs are the recent ones, and a file nobody trimmed grew for as long as the machine
239
+ deployed.
240
+
234
241
  ### The CI environment
235
242
 
236
243
  The build declares no variables of its own, but it reads the ones CI sets itself. That is why a pipeline needs neither a version flag nor an edit of the sources:
@@ -338,13 +345,14 @@ The server reads connection credentials from the same `ELEMENT_*` variables / `.
338
345
  | `get_build` | the whole card of one build; `version` is the build's version (`1.0-42`), an id is accepted too and resolved through the listing |
339
346
  | `build_assembly` | build a `.xasm`/`.xlib` archive from the sources locally (does not talk to the platform) |
340
347
  | `inspect_assembly` | parse a built archive: manifest, project properties, subsystems and global types with qualified names (local) |
341
- | `deploy` | the whole cycle from sources, with a check that the build was applied; the verdict is `ok`, the details are `problems` and `log`; a server that is still starting is waited out for up to `server_start_timeout` seconds (900 by default) |
348
+ | `deploy` | the whole cycle from sources, with a check that the build was applied; the verdict is `ok`, the details are `problems` and `log`; `allow_data_loss` lets through what the schema guard refuses (a narrowing, a type change, a catalog removed whole), like `--allow-data-loss`; a server that is still starting is waited out for up to `server_start_timeout` seconds (900 by default) |
342
349
  | `probe` | check the compilation with the server compiler without touching the working application; errors with file, line and column, cleans up after itself; with `keep` the report names the command that removes what was left |
343
- | `probe_cleanup` | remove a probe left on the stand, by `keep` or by a cleanup that broke off, starting from its application: the application, the probe build in the probe's own project and the project when nothing is left in it; an application that is not a probe's is refused |
350
+ | `probe_cleanup` | remove a probe left on the stand, by `keep` or by a cleanup that broke off, starting from its application: the application, the probe build in the probe's own project and the project when nothing is left in it; a probe given its own name and version is known by the local registry of uploads, which also names the builds deployed into it; an application that is not a probe's is refused |
344
351
  | `apply_build` | apply an uploaded build to the application by its id |
345
352
  | `verify_deploy` | verify the apply actually took effect: failed tasks, the applied build, the availability of the uri |
346
353
  | `list_user_lists` | user lists; `name` filters by a substring of the presentation |
347
354
  | `configure_user_list` | self-registration and password sign-in; without the flags it only reports the current state |
355
+ | `list_app_users` | who is connected to an application: the user list, the id, the presentation, whether an administrator and whether token access is on, with a count line; the platform gives no login here |
348
356
  | `token_access` | a user's access to the HTTP services of an application by a token, the flag behind a 500 "Token access is denied"; shows it, and with `enabled` switches it and reads it back; an empty `user` means the account elemctl signs in with |
349
357
  | `list_branches` | list of development-environment branches; the `project_id` and `name` filters are optional |
350
358
  | `merge_branch` | accept the changes of a development-environment branch |
@@ -358,7 +366,7 @@ A single environment is not a limit. Every tool that talks to the platform takes
358
366
 
359
367
  `list_projects` behaves the same way and returns id, name, project kind, space, application count and the deletion flag. Its `name` filters by a substring too, and projects marked deleted stay hidden until `include_deleted` is set: a stand a few months old keeps hundreds of them against a handful of live ones.
360
368
 
361
- `list_builds` answers with brief cards as well, holding id, versions, date, branch and commit, and with the ten newest builds unless `limit` says otherwise; 0 lifts the cut. The cards sit under `builds`, next to the counters `total` (how many builds the platform returned) and `shown`, plus a `summary` line. The platform's listing is not the project's whole history: it deletes the builds nobody uses, whatever their age. The build an application runs, the project's first build and a release build stay. The listing has no pages, and `summary` says plainly that what you see is the remainder of the history. It reads that off the answer itself: the platform hands out the numbers of one base version consecutively, so a number missing from the listing is a build already taken away.
369
+ `list_builds` answers with brief cards as well, holding id, versions, date, branch and commit, and with the ten newest builds unless `limit` says otherwise; 0 lifts the cut. The cards sit under `builds`, next to the counters `total` (how many builds the platform returned) and `shown`, plus a `summary` line. The platform's listing is not the project's whole history: it deletes the builds nobody uses, whatever their age. The build an application runs, the project's first build and a release build stay. The listing has no pages, and `summary` says plainly that what you see is the remainder of the history. It reads that off the answer itself: the platform hands out the numbers of one base version consecutively, so a number missing from the listing is a build already taken away – unless it is a jump. A build uploaded by the vendor and the name keeps the number of its archive and the count goes on from it, and a hole under such a build of this machine is named in `summary` as a jump rather than a deletion.
362
370
 
363
371
  `get_build` hands back one card whole and is addressed by the build version. An id is accepted as well and looked up in the listing, because the address the method understands is the version, not the id of a card.
364
372
 
@@ -173,8 +173,8 @@ for the cache to watch and stays pinned for the life of the process instead.
173
173
 
174
174
  ### Behaviour of the tool
175
175
 
176
- `ELEMCTL_LANG`, `ELEMCTL_NO_PLUGINS` and `ELEMCTL_DATA_DIR` are set through the
177
- environment only – a connection `.env` is not their place. `ELEMCTL_NO_PROXY` is the
176
+ `ELEMCTL_LANG`, `ELEMCTL_NO_PLUGINS`, `ELEMCTL_DATA_DIR` and `ELEMCTL_REGISTRY_LIMIT` are
177
+ set through the environment only – a connection `.env` is not their place. `ELEMCTL_NO_PROXY` is the
178
178
  exception, explained above: it reads the same file the connection does.
179
179
 
180
180
  | Variable | Purpose |
@@ -183,6 +183,7 @@ exception, explained above: it reads the same file the connection does.
183
183
  | `ELEMCTL_NO_PROXY` | set it to bypass the environment's proxy for every call (loopback and private addresses are bypassed anyway); also readable from the stand's `.env` |
184
184
  | `ELEMCTL_NO_PLUGINS` | do not look for plugins: work with the core capabilities only |
185
185
  | `ELEMCTL_DATA_DIR` | the directory of the local registry of uploads; by default `%LOCALAPPDATA%\elemctl` on Windows and `$XDG_STATE_HOME/elemctl` (`~/.local/state/elemctl`) elsewhere |
186
+ | `ELEMCTL_REGISTRY_LIMIT` | how many uploads the local registry of uploads keeps; 1000 by default, `0` keeps every one |
186
187
 
187
188
  ### The local registry of uploads
188
189
 
@@ -199,6 +200,12 @@ had no registry yet is not in it, and there the listings show what the platform
199
200
  registry that cannot be written is a warning and never a failed upload; the file can be
200
201
  deleted at any time, and only the history of this machine goes with it.
201
202
 
203
+ The registry keeps the newest thousand uploads, `ELEMCTL_REGISTRY_LIMIT` sets another
204
+ number, and `0` keeps every one. Once the file has grown past the limit by a tenth, the next
205
+ upload cuts it back to the newest lines: the builds a project still lists and an application
206
+ still runs are the recent ones, and a file nobody trimmed grew for as long as the machine
207
+ deployed.
208
+
202
209
  ### The CI environment
203
210
 
204
211
  The build declares no variables of its own, but it reads the ones CI sets itself. That is why a pipeline needs neither a version flag nor an edit of the sources:
@@ -306,13 +313,14 @@ The server reads connection credentials from the same `ELEMENT_*` variables / `.
306
313
  | `get_build` | the whole card of one build; `version` is the build's version (`1.0-42`), an id is accepted too and resolved through the listing |
307
314
  | `build_assembly` | build a `.xasm`/`.xlib` archive from the sources locally (does not talk to the platform) |
308
315
  | `inspect_assembly` | parse a built archive: manifest, project properties, subsystems and global types with qualified names (local) |
309
- | `deploy` | the whole cycle from sources, with a check that the build was applied; the verdict is `ok`, the details are `problems` and `log`; a server that is still starting is waited out for up to `server_start_timeout` seconds (900 by default) |
316
+ | `deploy` | the whole cycle from sources, with a check that the build was applied; the verdict is `ok`, the details are `problems` and `log`; `allow_data_loss` lets through what the schema guard refuses (a narrowing, a type change, a catalog removed whole), like `--allow-data-loss`; a server that is still starting is waited out for up to `server_start_timeout` seconds (900 by default) |
310
317
  | `probe` | check the compilation with the server compiler without touching the working application; errors with file, line and column, cleans up after itself; with `keep` the report names the command that removes what was left |
311
- | `probe_cleanup` | remove a probe left on the stand, by `keep` or by a cleanup that broke off, starting from its application: the application, the probe build in the probe's own project and the project when nothing is left in it; an application that is not a probe's is refused |
318
+ | `probe_cleanup` | remove a probe left on the stand, by `keep` or by a cleanup that broke off, starting from its application: the application, the probe build in the probe's own project and the project when nothing is left in it; a probe given its own name and version is known by the local registry of uploads, which also names the builds deployed into it; an application that is not a probe's is refused |
312
319
  | `apply_build` | apply an uploaded build to the application by its id |
313
320
  | `verify_deploy` | verify the apply actually took effect: failed tasks, the applied build, the availability of the uri |
314
321
  | `list_user_lists` | user lists; `name` filters by a substring of the presentation |
315
322
  | `configure_user_list` | self-registration and password sign-in; without the flags it only reports the current state |
323
+ | `list_app_users` | who is connected to an application: the user list, the id, the presentation, whether an administrator and whether token access is on, with a count line; the platform gives no login here |
316
324
  | `token_access` | a user's access to the HTTP services of an application by a token, the flag behind a 500 "Token access is denied"; shows it, and with `enabled` switches it and reads it back; an empty `user` means the account elemctl signs in with |
317
325
  | `list_branches` | list of development-environment branches; the `project_id` and `name` filters are optional |
318
326
  | `merge_branch` | accept the changes of a development-environment branch |
@@ -326,7 +334,7 @@ A single environment is not a limit. Every tool that talks to the platform takes
326
334
 
327
335
  `list_projects` behaves the same way and returns id, name, project kind, space, application count and the deletion flag. Its `name` filters by a substring too, and projects marked deleted stay hidden until `include_deleted` is set: a stand a few months old keeps hundreds of them against a handful of live ones.
328
336
 
329
- `list_builds` answers with brief cards as well, holding id, versions, date, branch and commit, and with the ten newest builds unless `limit` says otherwise; 0 lifts the cut. The cards sit under `builds`, next to the counters `total` (how many builds the platform returned) and `shown`, plus a `summary` line. The platform's listing is not the project's whole history: it deletes the builds nobody uses, whatever their age. The build an application runs, the project's first build and a release build stay. The listing has no pages, and `summary` says plainly that what you see is the remainder of the history. It reads that off the answer itself: the platform hands out the numbers of one base version consecutively, so a number missing from the listing is a build already taken away.
337
+ `list_builds` answers with brief cards as well, holding id, versions, date, branch and commit, and with the ten newest builds unless `limit` says otherwise; 0 lifts the cut. The cards sit under `builds`, next to the counters `total` (how many builds the platform returned) and `shown`, plus a `summary` line. The platform's listing is not the project's whole history: it deletes the builds nobody uses, whatever their age. The build an application runs, the project's first build and a release build stay. The listing has no pages, and `summary` says plainly that what you see is the remainder of the history. It reads that off the answer itself: the platform hands out the numbers of one base version consecutively, so a number missing from the listing is a build already taken away – unless it is a jump. A build uploaded by the vendor and the name keeps the number of its archive and the count goes on from it, and a hole under such a build of this machine is named in `summary` as a jump rather than a deletion.
330
338
 
331
339
  `get_build` hands back one card whole and is addressed by the build version. An id is accepted as well and looked up in the listing, because the address the method understands is the version, not the id of a card.
332
340
 
@@ -75,7 +75,7 @@ Common prefix: `{base}/console/api/v2`. Request and response bodies are JSON, ap
75
75
  - `PUT /applications/{id}/users/change-token-access` – switch that access. Body: `{"user-list-id", "user-id", "enable-access"}`, all three required; the answer is the connection as it became. A user who is not connected to the application is refused with a 500 "Can't change user token access" and no word about the cause, so the client finds the connection first and names the user when there is none. The reference documents the method under v2 and v2.1 with the same body, and a live check got the same answer from both; the client takes the v2 prefix, like every other request.
76
76
  - `GET /me` – the user the credentials belong to: `id`, `login`, `presentation`, `user-list-id`.
77
77
 
78
- Application statuses: stable `Running`, `Stopped`, `Error`; transitional `Starting`, `Stopping`, `Initializing`, `Updating`, `Frozen`, `Creating`. During transitions the `status` field may also be empty.
78
+ Application statuses: stable `Running`, `Stopped`, `Error`; transitional `Starting`, `Stopping`, `Initializing`, `Updating`, `Frozen`, `Creating`, `Deleting`. During transitions the `status` field may also be empty. The reference describes `status` as a plain string and lists no values, so this list is what live checks have met. `Deleting` lasts while the `DeleteApplication` task runs, and then the application stays in the list under `Deleted` (section 6.9). `UNKNOWN`, in capitals, was met on an application whose database files were gone: it could be neither started nor deleted, because a deletion begins with an export of the data. The client does not count it as a stable status, so a wait for one runs out its timeout on such an application and names the status.
79
79
 
80
80
  ### 4.2. Technology version
81
81
 
@@ -85,17 +85,18 @@ Application statuses: stable `Running`, `Stopped`, `Error`; transitional `Starti
85
85
  ### 4.3. Spaces and projects
86
86
 
87
87
  - `GET /spaces` – list of spaces.
88
- - `GET /projects` – list of projects; `GET /projects/{id}` – card; `DELETE /projects/{id}` – delete. The list is answered in full whatever the query, and deleted projects stay in it under the `deleted` flag with their former id. Filtering by name and hiding the deleted ones is the client's work, as with applications (section 4.1).
88
+ - `GET /projects` – list of projects; `GET /projects/{id}` – card; `DELETE /projects/{id}` – delete. The list is answered in full whatever the query, and deleted projects stay in it under the `deleted` flag with their former id. Filtering by name and hiding the deleted ones is the client's work, as with applications (section 4.1). A project card carries no status at all: the `deleted` flag is the only mark of its state.
89
89
 
90
90
  ### 4.4. Project builds (assemblies)
91
91
 
92
92
  - Uploading a build file – a binary POST (Content-Type `application/octet-stream`, body – the file bytes):
93
93
  - `POST /projects/{id}/assemblies` – add a build to an existing project;
94
- - `POST /projects` – create a new project from a build.
95
- The space goes as the optional `SpaceId` query parameter; note that its name is in PascalCase. The commit the build was made from goes as `commit-id`, a query parameter the reference documents for `POST /projects/{id}/assemblies`, and the server puts it on the build card: that is the commit the schema guard of the next deploy compares against (section 7). The reference lists `branch-name`, `commit-message` and `modified` for the same method too, and the client sends none of them. A live check found the server taking them and showing none on the card: its `branch-name` names a branch of group development, not of git, and `modified=1` is refused with a 500. The PascalCase `CommitId`, `BranchName` and `CommitMessage` are not parameters of the method at all, and the server ignores them. `POST /projects` documents no commit parameter, so a build that creates its project carries no commit. What the platform does not keep – the branch, whether the tree had uncommitted changes, the directory of the sources – the client keeps in a local registry of uploads (section 7). The response carries the id of the created build in one of the fields `image-id`, `assembly-id` or `id`, checked in that order. Next to it sits an `artifact` object describing the project the build landed in: `artifact-id` is the project id and opens as a project card, `configuration-id` is the `Ид` of `Проект.yaml`, and `name` is the project presentation. The console shows a project under the name of the last uploaded build, meaning the manifest `Name`. So a build uploaded into a project under a different name renames that project and its group, and deleting the build does not undo it. The client refuses such an upload and names the price; uploading a foreign build on purpose takes `--force-rename`. The check is best effort: when the names cannot be compared, because the manifest is unreadable or the project card is unreachable, the upload proceeds as before. Not being able to compare is no proof of danger.
94
+ - `POST /projects` – create a new project from a build, or add the build to the project the vendor and the name of the manifest already belong to;
95
+ - `POST /spaces/{space-id}/projects` – the same, with a new project created in that space.
96
+ The space of an upload into a project goes as the optional `space-id` query parameter, spelled the way the reference spells it. A live check found the server reading it: an id that is not a UUID is refused with a 400 and an unknown space with a 404, while the PascalCase `SpaceId` the client used to send went through unread. `POST /projects` documents no space parameter, and the server reads neither spelling there: a new project uploaded with `space-id=not-a-uuid` was created all the same. So the space of a new project goes into the path of `POST /spaces/{space-id}/projects`, which answers an unknown space with a 404 and adds a build whose vendor and name already have a project to that project, the way `POST /projects` does. The commit the build was made from goes as `commit-id`, a query parameter the reference documents for `POST /projects/{id}/assemblies`, and the server puts it on the build card: that is the commit the schema guard of the next deploy compares against (section 7). The reference lists `branch-name`, `commit-message` and `modified` for the same method too, and the client sends none of them. A live check found the server taking them and showing none on the card: its `branch-name` names a branch of group development, not of git, and `modified=1` is refused with a 500. The PascalCase `CommitId`, `BranchName` and `CommitMessage` are not parameters of the method at all, and the server ignores them. `POST /projects` documents no commit parameter, so a build that creates its project carries no commit. What the platform does not keep – the branch, whether the tree had uncommitted changes, the directory of the sources – the client keeps in a local registry of uploads (section 7). The two uploads treat the version of the archive differently. An upload into a project, `POST /projects/{id}/assemblies`, does not read it at all: the server takes the base from the `Версия` of the project descriptor and gives the build the highest number of that base plus one. Checked live: an archive of `1.0.0-i1` became `1.0.0-1`, the next one, `1.0.0-10001`, became `1.0.0-2`, a `1.0.0-2` already in the project became `1.0.0-3`, and `1.0.1-7` became `1.0.0-502` in a project whose descriptor says `1.0.0`. That upload answers with the card of the build, and its `assembly-version` is the number the server handed out. An upload by the vendor and the name, `POST /projects`, keeps the version of the archive as it is, a suffix that is not a number included, and answers a version the project already has with a 409 (below). So the suffix of a version, the number of a CI run for instance, survives the second way and never the first: what ties a build uploaded into a project to its run is the name of the archive and the commit on the card. The response carries the id of the created build in one of the fields `image-id`, `assembly-id` or `id`, checked in that order. Next to it sits an `artifact` object describing the project the build landed in: `artifact-id` is the project id and opens as a project card, `configuration-id` is the `Ид` of `Проект.yaml`, and `name` is the project presentation. The console shows a project under the name of the last uploaded build, meaning the manifest `Name`. So a build uploaded into a project under a different name renames that project and its group, and deleting the build does not undo it. The client refuses such an upload and names the price; uploading a foreign build on purpose takes `--force-rename`. The check is best effort: when the names cannot be compared, because the manifest is unreadable or the project card is unreachable, the upload proceeds as before. Not being able to compare is no proof of danger.
96
97
  - **A project is identified by the pair `Vendor` + `Name` of the manifest** (section 6.8). `POST /projects` therefore does not always create a project: when a project with that pair already exists, the build is added to it and its `artifact-id` comes back in the response. There are two ways to hit a 409 `ALREADY_EXISTS`. The first is uploading a version that is already there, answered with "Версия сборки ... уже присутствует в группе проекта". The second is registering the same vendor and name under another project, answered with "Сборка с именем поставщика ... уже зарегистрирована в другом проекте"; that one happens even with a freshly generated `Ид` in `Проект.yaml`.
97
98
  - `GET /projects/{id}/assemblies` – list of builds. Each element contains `assembly-version`, a string like `1.0-42`, and an id in `id` or `image-id`. The response is either an array or an object with the list in the `items` or `assemblies` field. **The method has no pages and reports no total.** `limit`, `size`, `pageSize`, `count`, `top`, `maxResults`, `page`, `pageNumber`, `offset`, `skip`, `from` and `start` are all ignored: the answers to every one of them match byte for byte, and neither the headers nor the body carry a counter or a cursor. Verified by live calls on two installations. **The platform deletes builds nobody uses,** and age has nothing to do with it: the vendor's help calls this automatic deletion of unused builds. A build an application runs is kept, and so are a library build another project uses, a release build, the project's default build and the build the project's repository was created from. Everything else goes when the collector gets to it. Seen live: seventeen builds of one day's series were made and one survived, the one the application runs, while a build from two months earlier is still listed because it is the project's first. So a listing is not the project's history and not a page of it. It is what survived, and the client must say so.
98
- - `GET /projects/{id}/assemblies/{version}` – build card, `DELETE .../{version}` – delete. The last segment is what the method calls it: the version, which is `assembly-version` or `project-version`, a string like `1.0-42`. It is not the id of the card: a UUID there is answered with a 404 "Assembly with version <uuid> not found". Checked live on two installations of different ages, both behave this way. The pages used to claim the opposite, that only a UUID works and a version gets a 400 "Version is not a valid UUID"; anyone following that claim was left with an unreachable card whichever form they gave. An id is still an address a caller holds: the build list prints it, and an upload answers with one. So the client accepts both forms and looks the value up in the build list to get the version the method takes. A value in no card is named as missing instead of becoming a 404 out of the depths of the platform. When the address is refused with a 400 or a 404, the client tries the id as the segment too: no reachable installation wants it, but the 400 the pages described had to come from somewhere, and the second spelling costs one request. Note that the platform renumbers the manifest version on upload. Deleting a build is rejected with a 500 while an application created from it still exists (section 6.9); once that application is really gone, the same request succeeds. A 500 is an answer, not a misunderstood address: it is raised as it is and never retried with another spelling.
99
+ - `GET /projects/{id}/assemblies/{version}` – build card, `DELETE .../{version}` – delete. The last segment is what the method calls it: the version, which is `assembly-version` or `project-version`, a string like `1.0-42`. It is not the id of the card: a UUID there is answered with a 404 "Assembly with version <uuid> not found". Checked live on two installations of different ages, both behave this way. The pages used to claim the opposite, that only a UUID works and a version gets a 400 "Version is not a valid UUID"; anyone following that claim was left with an unreachable card whichever form they gave. An id is still an address a caller holds: the build list prints it, and an upload answers with one. So the client accepts both forms and looks the value up in the build list to get the version the method takes. A value in no card is named as missing instead of becoming a 404 out of the depths of the platform. When the address is refused with a 400 or a 404, the client tries the id as the segment too: no reachable installation wants it, but the 400 the pages described had to come from somewhere, and the second spelling costs one request. The version of a build uploaded into a project is the number the server gave it, not the one of its archive (the upload above). Deleting a build is rejected with a 500 while an application created from it still exists (section 6.9); once that application is really gone, the same request succeeds. A 500 is an answer, not a misunderstood address: it is raised as it is and never retried with another spelling.
99
100
 
100
101
  Build versions are compared by the numeric suffix after the last hyphen: `1.0-10` is newer than `1.0-9`. Lexicographic comparison gives the wrong order.
101
102
 
@@ -201,7 +202,7 @@ Compatibility is checked against the `РежимСовместимости` prop
201
202
  10. **Compilation is the server's, and it happens on apply.** A local build only packs an archive. The syntax, the types and the visibility of the sources are checked by the server compiler when a build is applied or an application is created out of it. There is no separate "compile" endpoint, so the only way to check the sources without risking the working application is a throwaway application created from the same build (section 7, `probe`).
202
203
  11. **Signing in to a freshly created application.** A new application gets its own empty user list (`default-user-list`, section 4.7), password sign-in in it is off, and it has no account service. The accounts used to sign in to other applications therefore do not work here, and connecting another application's user list (`POST /applications/{id}/userlists`) together with enabling the local sign-in does not change that; this was verified. What works is a control-panel account: the platform connects its users to the application itself, and the sign-in works right away. The tool has to say so out loud when it creates an application (section 7, `apps create` and `apps ensure`): the way in does not follow from the card, and it cannot be found by trying, because a user has a failed-attempt counter.
203
204
  12. **A server that is still starting.** After a start or an update the server takes minutes to bring its console up; thirteen of them were seen after one update. All that time every console request, the token request included, is answered with a 404 whose text names the console application: `Application "console" not found`. That is the status a missing application or build gets, so only the text tells them apart. The client recognizes the answer in one place, for every request it makes, and raises an error that says what it means: the server is starting, repeat once `/console` answers 302. `deploy` waits it out by itself at any step of its cycle, for up to `--server-start-timeout` seconds (900 by default, 0 turns the wait off), and announces the start and the end of the wait. A request the console refused was never processed, so asking again is safe whatever its method. The other commands do not wait: they name the cause and stop.
204
- 13. **A removal is applied without a question.** A build whose sources no longer have a tabular part is applied as it is: the part goes, and its rows go with it. There is no refusal and no warning, the task ends well and the application keeps running; that was seen on a catalog with a row in the part. An attribute of a tabular part and an attribute of the object go the same way, with their values. A narrowed length or a changed type recreates the data of the object instead. What the deploy does about either is in section 7.
205
+ 13. **A removal is applied without a question.** A build whose sources no longer have a tabular part is applied as it is: the part goes, and its rows go with it. There is no refusal and no warning, the task ends well and the application keeps running; that was seen on a catalog with a row in the part. An attribute of a tabular part and an attribute of the object go the same way, with their values, and so does a catalog whose description is gone from the sources, with its whole table: that was seen on an empty catalog. A narrowed length or a changed type recreates the data of the object instead. What the deploy does about each is in section 7.
205
206
 
206
207
  ## 7. CLI requirements
207
208
 
@@ -225,11 +226,11 @@ Commands, with the significant flags in parentheses:
225
226
  --tech-version --no-dev-mode --wait --verify --no-verify --apply]`,
226
227
  `apps apply [APP_ID] VERSION_ID`,
227
228
  `apps delete APP_ID`, `apps start [APP_ID]`, `apps stop [APP_ID]`,
228
- `apps token-access APP_ID [--user --enable --disable]`.
229
+ `apps users [APP_ID]`, `apps token-access APP_ID [--user --enable --disable]`.
229
230
  - `apps list --name` filters by a case-insensitive name substring, and it does so on the client because the platform ignores the query parameter (section 4.1). `--status` selects by the whole status word, several of them separated by commas. `--brief` prints brief cards instead of full ones: id, name, status, uri, applied version.
230
231
  - `apps list` hides the deleted applications. They stay in the platform list under the `Deleted` status, and a stand a few months old answers with hundreds of cards of which a handful are alive. `--include-deleted` brings them back, and so does `--status deleted`: a filter that would answer with nothing is worse than no filter. A cut nobody is told about is a trap of its own, so the command ends with a count line on stderr, "7 live of 324", plus the number shown when a filter narrowed the answer further. Whatever is cut, stdout stays the same JSON array.
231
232
  - `apps get` adds `applied-build` to the card: the brief card of the build the application runs, with its branch and commit from the build card or from the local registry of uploads, in the shape `builds list --brief` prints. It is null when the card names no applied build.
232
- - `APP_ID` of `apps get`, `delete`, `start`, `stop` and `debug` is the application id (UUID) or its exact name. A value that is not a UUID is resolved through the list by an exact case-insensitive match, and deleted applications do not count. No match is an error, and several matches are an error listing the ids: destructive commands must not guess.
233
+ - `APP_ID` of `apps get`, `delete`, `start`, `stop`, `debug` and `users` is the application id (UUID) or its exact name. A value that is not a UUID is resolved through the list by an exact case-insensitive match, and deleted applications do not count. No match is an error, and several matches are an error listing the ids: destructive commands must not guess.
233
234
  - `apps find` searches for an exact, case-insensitive name match among the fields `name`, `display-name` and `publication-context`. Output is `{"id": ..., "found": true|false}` with return code 0 in both cases: the absence of an application is an answer, not an error. A non-zero return code means the request failed and comes with JSON carrying an `error` field on stderr. In scripts, check the `found` field, not the return code.
234
235
  - Deleted applications remain in the platform list with the `Deleted` status and their former `id`. `apps find` skips them: the found id must be usable, otherwise the caller gets an id on which `apps get` and `deploy` return 404. The `--include-deleted` flag restores the former behaviour, searching among all applications including deleted ones.
235
236
  - `apps ensure` idempotently brings an application with the given name into existence: it searches by the `apps find` rules, where deleted ones do not count, and creates only if absent. Output is `{"id": ..., "created": true|false, "sign-in": ...}`, and `created: false` means the application already existed and was left alone. The creation flags are the same as for `apps create` and take effect only when creation happens. An existing application is never recreated: `delete` and `create` produce a new URL and break external bindings to the former one. Because the creation flags include `--version-id`, an existing application gets two more fields in the answer: `applied`, whether it runs the requested assembly, and `applied-version-id`, the one it does run. Staying silent about that cost a stand that went to work on the previous build. `--apply` brings it to the assembly in the same call, and `apps apply` does it separately. `--verify` upgrades the verdict about an application that already runs the requested assembly from the card comparison to the full check. An application `ensure` had created used to answer `applied: true` on trust, since it was created from that assembly, and now answers with the checked verdict whenever a check ran.
@@ -239,6 +240,7 @@ Commands, with the significant flags in parentheses:
239
240
  - A source given by `--version-id` is looked up in the build list of the project before anything is created. The project is `--project-id`, or `ELEMENT_PROJECT_ID` when the flag is absent. The platform deletes the builds nobody uses and cannot create an application from a deleted one: it answers with a bare 400 "Can't create application", which reads like a limit on the number of applications. So the command refuses by itself. The refusal names the cause and offers the build that a running application of the project runs, or `--latest-build` when no application runs one. A project taken from `ELEMENT_PROJECT_ID` is named in the refusal, because the build may belong to another project. Without a project there is no list to look in, and the create goes as before.
240
241
  - Waiting means verifying. A failed apply is rolled back by the platform to the previous build, and the application comes up `Running` all the same, so a card handed back after a wait is not evidence that the build asked for is the one running. `--wait` therefore ends with the same check `apps apply` and `verify-deploy` do: the applied build id against the requested one, the application tasks that failed since the creation started, the uri. It puts the report into the `verify` field of the output and answers with exit code 1 when the check does not pass. `--verify` asks for the check on its own, and waits too, because there is nothing to check on an application still being created. `--no-verify` brings back the plain wait. Without either flag nothing is waited for and nothing is checked, as before.
241
242
  - The application exists once the create has answered, so a wait or a check that breaks off does not lose it. The output still carries the id: the card of `apps create`, the `id` of `apps ensure` with `applied: null`, since nothing was checked. The `wait-error` field holds the error that ended the wait, stderr names the `verify-deploy` call that checks the build later, and the exit code is 1. The answer used to be a bare network error without the id, and the id of an application that came up minutes later had to be looked up by name.
243
+ - `apps users [APP_ID]` prints the users connected to the application the way `GET /applications/{id}/users` gives them (section 4.1): `user-list-id`, `user-id`, `presentation`, `is-admin`, `token-access-enabled`. There is no login among them: the platform names a user of the control panel by the login in `presentation` and any other user by its presentation. The command only reads, so the application defaults to `ELEMENT_APP_ID`, and it ends with a count line on stderr: how many users are connected, how many of them administer the application and how many reach its HTTP services by a token. Until the command the list was seen only in a refusal of `apps token-access`.
242
244
  - `apps token-access APP_ID` shows or switches the access of a user to the HTTP services of the application by a token (section 4.1). The application is named explicitly, by the argument or by `--app-id`: `ELEMENT_APP_ID` names the working application, and a switch that opens its services must not land there by default. `--user` is a login, a presentation or a user id, and without it the command speaks about the account elemctl itself signs in with (`GET /me`). Without `--enable` or `--disable` it only reads; both at once is an error. A switch reads the connection back, so `token-access-enabled` in the output is what the platform keeps after the change, and a flag that did not move is an error with exit code 1. The output is `{"app-id", "user", "user-id", "user-list-id", "token-access-enabled", "changed"}`, where `changed` says whether this very call altered anything: the state that is already there sends no request. A user who is not connected to the application is named as such, with the users that are, before anything is sent.
243
245
  - `spaces list`.
244
246
  - `user-lists list [--name]`, `user-lists get [LIST] [--app]`,
@@ -260,6 +262,7 @@ Commands, with the significant flags in parentheses:
260
262
  `builds upload FILE [--project-id --new-project --force-rename --space-id]`,
261
263
  `builds delete VERSION [--project-id]`.
262
264
  `builds upload` sends the commit the manifest of the archive names as `commit-id`
265
+ (section 4.4), names on stderr a build the server numbered otherwise than its archive
263
266
  (section 4.4) and reports the chosen target in the output through `project-id` and
264
267
  `project-id-source` (`flag`, `env` or none) and notes on stderr when the target comes
265
268
  from `ELEMENT_PROJECT_ID`. `--new-project` ignores the environment binding and always
@@ -271,8 +274,16 @@ Commands, with the significant flags in parentheses:
271
274
  uses, whatever their age). "30 of 30" without that line was read as the project's whole
272
275
  history. The housekeeping is judged by the facts of the answer, not by the length of the
273
276
  listing: the platform hands out the numbers of a base version one after another, so a
274
- number the listing has not got is a build already taken away, and the line says how many
275
- are missing.
277
+ hole in the numbering is a build already taken away, and the line says there are holes
278
+ without counting them. A hole can also be a jump: an upload by the vendor and the name
279
+ keeps the number of its archive, and the next upload into the project counts on from
280
+ it. Seen live, `1.0.0-3` was followed by `1.0.0-500` and `1.0.0-501`, and the numbers
281
+ between had never existed. The created stamps of the neighbours cannot tell a jump
282
+ from a loss, since the server handed out four numbers in a third of a second, so the
283
+ local registry of uploads does: a hole under a build this machine uploaded by the
284
+ vendor and the name is named as a jump and is no evidence of the housekeeping. A build
285
+ uploaded that way from elsewhere is not in the registry, and its hole still reads as a
286
+ deletion.
276
287
  `--brief` prints the id, the versions, the date, the branch and the commit of a build.
277
288
  The branch and the commit come from the card when the platform filled them, otherwise
278
289
  from the local registry of uploads, and `branch-name-source` and `commit-id-source`
@@ -284,13 +295,22 @@ Commands, with the significant flags in parentheses:
284
295
  `ELEMCTL_DATA_DIR` when it is set, otherwise `%LOCALAPPDATA%\elemctl` on Windows and
285
296
  `$XDG_STATE_HOME/elemctl` (`~/.local/state/elemctl`) elsewhere. A line holds the build
286
297
  id, the project id, the version, the branch, the commit, the `dirty` flag, the directory
287
- of the sources, the archive, the stand, the command and the time. The platform keeps the
288
- commit alone, and with several sessions deploying from one machine a build on an
289
- application could not be traced to the working tree it came from. The registry is
290
- local: a build uploaded from another machine, from CI or by an elemctl that had no
291
- registry yet is not in it. A registry that cannot be written is a warning on stderr,
292
- never a failure – the build is on the server by then – and one that cannot be read
293
- reads as empty.
298
+ of the sources, the archive, the stand, the command, the application the upload was made
299
+ for (the target of a deploy, the throwaway application of a probe), the route of the
300
+ upload (`project` into a project by its id, `vendor-name` by the vendor and the name)
301
+ and the time. The platform keeps the commit alone, and with several sessions deploying
302
+ from one machine a build on an application could not be traced to the working tree it
303
+ came from. The registry is local:
304
+ a build uploaded from another machine, from CI or by an elemctl that had no registry yet
305
+ is not in it. A registry that cannot be written is a warning on stderr, never a failure
306
+ – the build is on the server by then – and one that cannot be read reads as empty. The
307
+ schema guard of `deploy` takes the commit of an applied build from here when the card of
308
+ that build carries none. The registry keeps the newest 1000 uploads,
309
+ `ELEMCTL_REGISTRY_LIMIT` sets another number and `0` keeps every one: once the file has
310
+ grown past the limit by a tenth, the next upload cuts it back to the newest lines. The
311
+ file is rewritten beside itself and swapped in by a rename, and a line another process
312
+ appended meanwhile is carried over; a swap the system refuses leaves the file as it was
313
+ until the next upload.
294
314
  - `build [--project-dir --output --build-version --last-build --commit
295
315
  --branch --kind {application,library} --require-clean]` – build the archive locally.
296
316
  Output: `file`, `name`, `vendor`, `version`, `version-source`
@@ -307,9 +327,9 @@ Commands, with the significant flags in parentheses:
307
327
  - `deploy [--app-id --project-id --project-dir --output --build-version
308
328
  --branch --commit --dry-run --require-clean --allow-data-loss
309
329
  --server-start-timeout]` –
310
- the full cycle: build -> upload -> apply -> restart -> verification of the actual apply (section 6.1). Output – a JSON report with fields: `app-id`, `uri`, `status`, `version`, `assembly-id`, `applied-version`, `applied` (true, false or null, where null means the actual version could not be determined), `uri-status`, `problems` (list of strings, the platform's texts as they came), `problems-lines` (the same broken into plain lines: JSON escapes a multi-line refusal into `
311
- ` and ` ` exactly where it has to be read), `ok` (boolean), `dirty` and `dirty-files` (uncommitted changes of the project directory at build time). The build captures the current disk state, so the divergence from HEAD must be visible; a warning also goes to stderr, and null means git was unavailable. `hint` points at the log of the server when a task was refused without a compilation error in its text. The platform may answer with "Contact administrator for details" alone, and the cause then sits in the server log: the last `Caused by` line, with `SrcPath:` beside it naming the file the apply stopped at. An apply that leaves the application in `Error` ends the deploy with an error, and that error carries the same hint. Return code 0 only when `ok`. `--dry-run` builds and stops there, and `--require-clean` aborts before building on a dirty tree. `--server-start-timeout` is how many seconds a server that is still starting is waited out (section 6.12).
312
- Before anything is built, the schema guard reads the sources against the commit the applied build was made from, the `commit-id` of its card (section 4.4). The project directory is found the way the build finds it. A narrowed length or a changed type of an attribute, a dimension or a resource, the attributes of a tabular part included, and a removed dimension recreate or break the data, so the deploy refuses them unless `--allow-data-loss` is given. A removed attribute, resource, tabular part or attribute of a tabular part is a deliberate edit the server applies without asking (section 6.13): the deploy names each one on stderr and in the `schema-warnings` field and goes on. Fields are matched by `Ид`, so a rename keeps its data, and across a translation of the description only an `Ид` can tell that an element is gone. `schema-check` says what the guard did: `clean`, `warned` (removals only), `allowed`, or `skipped:<reason>` when there was nothing to compare against: `no-project-dir`, `read-failed`, `no-applied-build`, `applied-build-not-listed`, `no-commit-id` or `commit-unavailable`, each explained in words of its own. A skipped check is said once more after the verdict: a passed verification alone read as if the schema had been checked too.
330
+ the full cycle: build -> upload -> apply -> restart -> verification of the actual apply (section 6.1). Output – a JSON report with fields: `app-id`, `uri`, `status`, `version`, `assembly-id`, `assembly-version` (the version the server gave the uploaded build), `renumbered` (true when that is not the version of the archive, null when the upload did not say), `applied-version`, `applied` (true, false or null, where null means the actual version could not be determined), `uri-status`, `problems` (list of strings, the platform's texts as they came), `problems-lines` (the same broken into plain lines: JSON escapes a multi-line refusal into `
331
+ ` and ` ` exactly where it has to be read), `ok` (boolean), `dirty` and `dirty-files` (uncommitted changes of the project directory at build time). The build captures the current disk state, so the divergence from HEAD must be visible; a warning also goes to stderr, and null means git was unavailable. `hint` points at the log of the server when a task was refused without a compilation error in its text. The platform may answer with "Contact administrator for details" alone, and the cause then sits in the server log: the last `Caused by` line, with `SrcPath:` beside it naming the file the apply stopped at. An apply that leaves the application in `Error` ends the deploy with an error, and that error carries the same hint. The server numbers a build uploaded into a project itself (section 4.4), so an explicit `--build-version` it will not keep – a suffix that is not a number, no suffix at all, a base other than the `Версия` of the project – is named on stderr before the build, and a build the server numbered otherwise than its archive is named right after the upload. Return code 0 only when `ok`. `--dry-run` builds and stops there, and `--require-clean` aborts before building on a dirty tree. `--server-start-timeout` is how many seconds a server that is still starting is waited out (section 6.12).
332
+ Before anything is built, the schema guard reads the sources against the commit the applied build was made from: the `commit-id` of its card (section 4.4), or, when the card carries none, the commit the local registry of uploads remembers for that build. A build that created its project has no commit on its card, and the registry knows one when the build was uploaded from this machine; a line on stderr says the commit came from there, and whether that build was made from a tree with uncommitted changes, which the comparison cannot see. `schema-commit` names the commit compared against and `schema-commit-source` where it came from, `platform` or `registry`. The project directory is found the way the build finds it. A narrowed length or a changed type of an attribute, a dimension or a resource, the attributes of a tabular part included, and a removed dimension recreate or break the data, so the deploy refuses them unless `--allow-data-loss` is given. So does an element that keeps data of its own – a catalog, a document, an information or accumulation register, a constants set, an exchange plan or a settings storage – whose description is gone from the sources: its whole table goes with every row. The disk cannot tell of a file that is not there, so the guard lists the files of the applied commit with git and follows an element by its `Ид`. A description moved to another subsystem or renamed keeps its data and is compared with its old text; an element without an `Ид` cannot be told from a moved one and is left alone. A file still in its place that carries another `Ид` describes another element: the description was made anew, and the element it used to describe is followed the same way. Checked live, a catalog described anew under its old path and name was applied without a question and came out empty, so such an element is refused as a removal, and the refusal names the former `Ид` to give back when the element is meant to be the same. The fields of the two descriptions are not compared with each other: they belong to different elements. A removed attribute, resource, tabular part or attribute of a tabular part is a deliberate edit the server applies without asking (section 6.13): the deploy names each one on stderr and in the `schema-warnings` field and goes on. Fields are matched by `Ид`, so a rename keeps its data, and across a translation of the description only an `Ид` can tell that an element is gone. `schema-check` says what the guard did: `clean`, `warned` (removals only), `allowed`, or `skipped:<reason>` when there was nothing to compare against: `no-project-dir`, `read-failed`, `no-applied-build`, `applied-build-not-listed`, `no-commit-id` or `commit-unavailable`, each explained in words of its own. A skipped check is said once more after the verdict: a passed verification alone read as if the schema had been checked too.
313
333
  - `verify-deploy [APP_ID] [--app-id --version-id --expected-version --since-minutes]` –
314
334
  the verification of section 6.1 on its own, deploying nothing. It looks at the
315
335
  application tasks in an error status raised over the last `--since-minutes` minutes,
@@ -371,25 +391,30 @@ Commands, with the significant flags in parentheses:
371
391
  refused with a 500 until the application is gone. Both lines name the `--env-file`
372
392
  the probe was run with.
373
393
  `probe --cleanup APP_ID` removes a probe left on the stand, starting from its
374
- application, an id or a name. The application card names the project and the build
375
- it was created from, so nothing has to be remembered between the runs. Only a
376
- probe's application is touched: its name starts with `elemctl-probe-`, or the build
377
- it runs carries `-probe-` in its version, which covers a probe named with `--name`.
378
- Any other application is refused with the reason, and so is the one
379
- `ELEMENT_APP_ID` names. The order is that of section 6.9: the application, a wait
380
- until it is gone, the build of this very probe (its token in the version), and the
381
- project last. The project goes only when no build is left in it and no live
382
- application runs it, and never when it is the project of `ELEMENT_PROJECT_ID`: a
383
- probe usually lands in the project that owns its sources, the working one, while a
384
- project the probe created ends up empty. The builds other runs uploaded into the
385
- probe's application are left to the platform, which deletes the builds nobody
386
- uses. A second run finishes what the first one left: an application that is
387
- already a tombstone is not deleted twice, since the list keeps its card, and a
388
- project deleted already is not deleted again. The run builds nothing, so the flags
389
- of a probe run are refused beside `--cleanup`. Output: `ok`, `app-id`, `app-name`,
394
+ application, an id or a name. The application card names the project and the build it
395
+ was created from, so nothing has to be remembered between the runs. Only a probe's
396
+ application is touched: its name starts with `elemctl-probe-`, or the build it runs
397
+ carries `-probe-` in its version, which covers a probe named with `--name`, or the local
398
+ registry of uploads remembers a probe of this machine creating it, which covers a probe
399
+ given both `--name` and `--build-version` and one that got deploys of its own since. Any
400
+ other application is refused with the reason, and so is the one `ELEMENT_APP_ID` names.
401
+ The order is that of section 6.9: the application, a wait until it is gone, the build of
402
+ this very probe (its token in the version, or the build the registry remembers the probe
403
+ uploading) together with every build the registry remembers uploading for this
404
+ application, and the project last. A build uploaded for the application that another
405
+ live application runs now stays, and its entry in `builds` names that application in
406
+ `kept`. The project goes only when no build is left in it and no live application runs
407
+ it, and never when it is the project of `ELEMENT_PROJECT_ID`: a probe usually lands in
408
+ the project that owns its sources, the working one, while a project the probe created
409
+ ends up empty. The builds other runs uploaded into the probe's application from another
410
+ machine, which the registry does not know, are left to the platform, which deletes the
411
+ builds nobody uses. A second run finishes what the first one left: an application that
412
+ is already a tombstone is not deleted twice, since the list keeps its card, and a
413
+ project deleted already is not deleted again. The run builds nothing, so the flags of a
414
+ probe run are refused beside `--cleanup`. Output: `ok`, `app-id`, `app-name`,
390
415
  `project-id`, `app-deleted`, `builds` (`{id, version, deleted}` each),
391
- `project-deleted`, `project-kept` (why the project stayed) and `problems`; return
392
- code 0 only when `ok`.
416
+ `project-deleted`, `project-kept` (why the project stayed) and `problems`; return code 0
417
+ only when `ok`.
393
418
  - `branches list [--project-id --name]`, `branches get ID`,
394
419
  `branches create NAME [--project-id --app-id]`,
395
420
  `branches update ID [--app-id]`, `branches delete ID`,
@@ -437,15 +462,18 @@ id (UUID) or the exact application name (resolved like the CLI does),
437
462
  `list_projects(name="", include_deleted=False)` – the filters of `projects list` (section 7),
438
463
  `list_builds(project_id, limit=10, brief=True)` – an object `{total, shown, summary, builds}`:
439
464
  the listing has to say whether it is the whole store, judged by the gaps in the build
440
- numbering (section 4.4), and a brief card names the source of its branch and commit, the
465
+ numbering (section 4.4) and naming a jump the local registry explains (section 7), and a
466
+ brief card names the source of its branch and commit, the
441
467
  card or the local registry of uploads, the way `builds list --brief` does (section 7),
442
468
  `get_build(project_id, version)` – the whole card of one build, addressed by the build
443
469
  version (section 4.4; an id is accepted and resolved through the listing),
444
470
  `build_assembly(project_dir="", output_dir="", version="")`,
445
471
  `inspect_assembly(file)` – parsing of a built archive (section 5.1; a local operation),
446
- `deploy(app_id, project_id, project_dir="", version="", branch="",
472
+ `deploy(app_id, project_id, project_dir="", version="", branch="", allow_data_loss=False,
447
473
  server_start_timeout=900)` – returns the deploy report plus a `log` field with progress
448
- lines, and waits out a server that is still starting (section 6.12); `probe(project_dir="", space_id="", keep=False)` – an isolated
474
+ lines, and waits out a server that is still starting (section 6.12); `allow_data_loss=True`
475
+ lets through what the schema guard refuses, the way `--allow-data-loss` does in the CLI
476
+ (section 7), and without it the refusal comes back as an error before anything is built; `probe(project_dir="", space_id="", keep=False)` – an isolated
449
477
  compilation check that does not touch the working application (section 7),
450
478
  the report plus a `log` field; `probe_cleanup(app_id)` – `probe --cleanup` (section 7),
451
479
  the removal of a probe left on the stand, the report plus a `log` field; `apply_build(app_id, version_id)`, `verify_deploy(app_id,
@@ -456,7 +484,9 @@ expected_version="", since_minutes=30)` – verification of the apply per sectio
456
484
  the sign-in settings of a user list (section 4.7) in one call: the list is given by id, by
457
485
  presentation or by the application whose own list it is; both flags are optional, and
458
486
  without them the tool only reports the state (`self-registration-enabled`,
459
- `password-login-enabled`, `changed`); `token_access(app_id, user="", enabled=None)` – the
487
+ `password-login-enabled`, `changed`); `list_app_users(app_id)` – the users connected to
488
+ the application as `apps users` shows them (section 7), in an object
489
+ `{app-id, total, summary, users}`; `token_access(app_id, user="", enabled=None)` – the
460
490
  access of a user to the HTTP services of the application by a token, as `apps token-access`
461
491
  shows and switches it (section 7): `app_id` is required, an empty `user` means the account
462
492
  elemctl signs in with, and without `enabled` the tool only reads.