@skillcdn/console 0.1.13 → 0.1.15

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 (170) hide show
  1. package/README.md +5 -4
  2. package/SKILLCDN.md +2 -0
  3. package/dist/agent-name.d.ts +3 -0
  4. package/dist/agent-name.d.ts.map +1 -0
  5. package/dist/agent-name.js +9 -0
  6. package/dist/agent-name.js.map +1 -0
  7. package/dist/api.d.ts +6 -4
  8. package/dist/api.d.ts.map +1 -1
  9. package/dist/api.js +6 -4
  10. package/dist/api.js.map +1 -1
  11. package/dist/cli/cli.d.ts +2 -0
  12. package/dist/cli/cli.d.ts.map +1 -1
  13. package/dist/cli/cli.js +215 -22
  14. package/dist/cli/cli.js.map +1 -1
  15. package/dist/cli/format.d.ts +14 -4
  16. package/dist/cli/format.d.ts.map +1 -1
  17. package/dist/cli/format.js +59 -10
  18. package/dist/cli/format.js.map +1 -1
  19. package/dist/cli/help.d.ts.map +1 -1
  20. package/dist/cli/help.js +27 -11
  21. package/dist/cli/help.js.map +1 -1
  22. package/dist/cli/main.js +5 -0
  23. package/dist/cli/main.js.map +1 -1
  24. package/dist/client.d.ts +20 -2
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +11 -2
  27. package/dist/client.js.map +1 -1
  28. package/dist/components/calendar.d.ts +15 -0
  29. package/dist/components/calendar.d.ts.map +1 -1
  30. package/dist/components/calendar.js +78 -41
  31. package/dist/components/calendar.js.map +1 -1
  32. package/dist/components/connect.d.ts +4 -1
  33. package/dist/components/connect.d.ts.map +1 -1
  34. package/dist/components/connect.js +7 -3
  35. package/dist/components/connect.js.map +1 -1
  36. package/dist/components/decision-list.d.ts.map +1 -1
  37. package/dist/components/decision-list.js +3 -3
  38. package/dist/components/decision-list.js.map +1 -1
  39. package/dist/components/documents.d.ts +5 -0
  40. package/dist/components/documents.d.ts.map +1 -1
  41. package/dist/components/documents.js +3 -2
  42. package/dist/components/documents.js.map +1 -1
  43. package/dist/components/event-feed.d.ts +1 -1
  44. package/dist/components/event-feed.d.ts.map +1 -1
  45. package/dist/components/event-feed.js +10 -1
  46. package/dist/components/event-feed.js.map +1 -1
  47. package/dist/components/people.d.ts +24 -1
  48. package/dist/components/people.d.ts.map +1 -1
  49. package/dist/components/people.js +35 -3
  50. package/dist/components/people.js.map +1 -1
  51. package/dist/components/projects.d.ts +6 -0
  52. package/dist/components/projects.d.ts.map +1 -1
  53. package/dist/components/projects.js +3 -3
  54. package/dist/components/projects.js.map +1 -1
  55. package/dist/components/rules.d.ts +40 -0
  56. package/dist/components/rules.d.ts.map +1 -0
  57. package/dist/components/rules.js +46 -0
  58. package/dist/components/rules.js.map +1 -0
  59. package/dist/components/runs.d.ts +1 -1
  60. package/dist/components/runs.d.ts.map +1 -1
  61. package/dist/components/runs.js +2 -1
  62. package/dist/components/runs.js.map +1 -1
  63. package/dist/components/skills.d.ts.map +1 -1
  64. package/dist/components/skills.js +5 -1
  65. package/dist/components/skills.js.map +1 -1
  66. package/dist/components/tokens.d.ts.map +1 -1
  67. package/dist/components/tokens.js +2 -9
  68. package/dist/components/tokens.js.map +1 -1
  69. package/dist/components/ui.d.ts +7 -2
  70. package/dist/components/ui.d.ts.map +1 -1
  71. package/dist/components/ui.js +13 -0
  72. package/dist/components/ui.js.map +1 -1
  73. package/dist/components/work.d.ts +9 -1
  74. package/dist/components/work.d.ts.map +1 -1
  75. package/dist/components/work.js +8 -3
  76. package/dist/components/work.js.map +1 -1
  77. package/dist/connect-page.d.ts.map +1 -1
  78. package/dist/connect-page.js +1 -1
  79. package/dist/connect-page.js.map +1 -1
  80. package/dist/console.css +253 -13
  81. package/dist/console.d.ts.map +1 -1
  82. package/dist/console.js +203 -49
  83. package/dist/console.js.map +1 -1
  84. package/dist/data.d.ts +19 -2
  85. package/dist/data.d.ts.map +1 -1
  86. package/dist/data.js +27 -1
  87. package/dist/data.js.map +1 -1
  88. package/dist/dates.d.ts +4 -0
  89. package/dist/dates.d.ts.map +1 -1
  90. package/dist/dates.js +26 -0
  91. package/dist/dates.js.map +1 -1
  92. package/dist/i18n/en.d.ts +90 -28
  93. package/dist/i18n/en.d.ts.map +1 -1
  94. package/dist/i18n/en.js +89 -31
  95. package/dist/i18n/en.js.map +1 -1
  96. package/dist/i18n/ko.d.ts.map +1 -1
  97. package/dist/i18n/ko.js +89 -31
  98. package/dist/i18n/ko.js.map +1 -1
  99. package/dist/index.d.ts +6 -5
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +6 -5
  102. package/dist/index.js.map +1 -1
  103. package/dist/limits.d.ts +4 -0
  104. package/dist/limits.d.ts.map +1 -1
  105. package/dist/limits.js +4 -0
  106. package/dist/limits.js.map +1 -1
  107. package/dist/router.d.ts +34 -2
  108. package/dist/router.d.ts.map +1 -1
  109. package/dist/router.js +55 -7
  110. package/dist/router.js.map +1 -1
  111. package/dist/routes.d.ts +14 -4
  112. package/dist/routes.d.ts.map +1 -1
  113. package/dist/routes.js +17 -2
  114. package/dist/routes.js.map +1 -1
  115. package/dist/rules.d.ts +28 -0
  116. package/dist/rules.d.ts.map +1 -0
  117. package/dist/rules.js +102 -0
  118. package/dist/rules.js.map +1 -0
  119. package/dist/schemas.d.ts +652 -4
  120. package/dist/schemas.d.ts.map +1 -1
  121. package/dist/schemas.js +96 -6
  122. package/dist/schemas.js.map +1 -1
  123. package/dist/vocabulary.d.ts +21 -1
  124. package/dist/vocabulary.d.ts.map +1 -1
  125. package/dist/vocabulary.js +21 -0
  126. package/dist/vocabulary.js.map +1 -1
  127. package/docs/specs/cli.md +13 -9
  128. package/docs/specs/rest.md +32 -8
  129. package/package.json +1 -1
  130. package/skills/building-a-console/SKILL.md +1 -1
  131. package/skills/deploying-a-console/SKILL.md +5 -5
  132. package/skills/deploying-a-console/assets/secrets.example.json +2 -1
  133. package/skills/deploying-a-console/references/access.md +10 -6
  134. package/skills/deploying-a-console/references/resources.md +10 -7
  135. package/skills/working-the-board/SKILL.md +10 -9
  136. package/skills/working-the-board/references/project-rules.md +36 -0
  137. package/src/agent-name.ts +9 -0
  138. package/src/api.ts +37 -0
  139. package/src/cli/cli.ts +253 -24
  140. package/src/cli/format.ts +74 -10
  141. package/src/cli/help.ts +30 -10
  142. package/src/cli/main.ts +5 -0
  143. package/src/client.ts +47 -1
  144. package/src/components/calendar.tsx +242 -101
  145. package/src/components/connect.tsx +12 -6
  146. package/src/components/decision-list.tsx +2 -2
  147. package/src/components/documents.tsx +7 -3
  148. package/src/components/event-feed.tsx +16 -3
  149. package/src/components/people.tsx +244 -35
  150. package/src/components/projects.tsx +31 -8
  151. package/src/components/rules.tsx +167 -0
  152. package/src/components/runs.tsx +4 -2
  153. package/src/components/skills.tsx +22 -11
  154. package/src/components/tokens.tsx +2 -14
  155. package/src/components/ui.tsx +25 -2
  156. package/src/components/work.tsx +69 -43
  157. package/src/connect-page.tsx +0 -1
  158. package/src/console.tsx +531 -67
  159. package/src/data.ts +52 -2
  160. package/src/dates.ts +28 -0
  161. package/src/i18n/en.ts +99 -38
  162. package/src/i18n/ko.ts +95 -38
  163. package/src/index.ts +21 -1
  164. package/src/limits.ts +4 -0
  165. package/src/router.ts +77 -12
  166. package/src/routes.ts +23 -3
  167. package/src/rules.ts +109 -0
  168. package/src/schemas.ts +121 -4
  169. package/src/styles/console.css +253 -13
  170. package/src/vocabulary.ts +30 -0
@@ -11,7 +11,7 @@ The API is the board as its members see it: the people, the projects, and in eac
11
11
  - Every answer is `cache-control: no-store`: it is one person's, or it changes.
12
12
  - A request that changes something (`POST`, `PATCH`, `DELETE`) on a session must carry the session cookie **and** come from the console's own pages: the browser's `origin` header must be `PUBLIC_URL`. The cookie is `SameSite=Lax`, so another site's request does not carry it in the first place; the origin is the second fence.
13
13
  - A token ([`POST /api/v1/tokens`](#get-apiv1tokens-and-post-apiv1tokens)) is presented as `Authorization: Bearer <secret>` on any route, by an agent, a script or a console of a person's own. It is then the credential: a cookie beside it is not looked at, and no origin is needed, since nothing attaches a token but whoever holds it. A token that is nothing is refused, whatever cookie travels with it. What a token does is attributed to its person, and the event names the agent: the token's name, or what the agent called itself on its run.
14
- - A token configures as its person does ([ADR-0021](../adr/0021-a-token-configures-as-its-person-does.md)): every request a session may make, a token may make, within the same roles, except the tokens themselves and the approval of a connection, which stay a person's own doing, signed in on the console's own pages.
14
+ - A token configures as its person does ([ADR-0021](../adr/0021-a-token-configures-as-its-person-does.md)): every request a session may make, a token may make, within the same roles, except the tokens themselves and the approval of a connection, which stay a person's own doing, signed in on the console's own pages; the one thing a token does about the tokens is give itself up (`DELETE /api/v1/me/token`).
15
15
  - An agent connects without anyone copying a token ([ADR-0011](../adr/0011-an-agent-connects-with-a-short-code-a-person-approves-and-the-token-is-never-shown.md)): [`POST /api/v1/connect`](#connecting-an-agent) is nobody's, the approval is a person's own doing on the console's own pages, and the claim is the command's, with the secret it was given.
16
16
  - Request bodies are JSON, at most 256 KiB, and parsed once with the package's input schema. Text is trimmed where it is a line, bounded everywhere (`MAX_TITLE_LENGTH` and the rest of `@skillcdn/console/api`), and refused when it carries control or invisible characters. Links are `https` URLs only.
17
17
  - Errors have `{ "error": { "code": "...", "message": "..." } }`. The code is stable; the message is for a person, in English.
@@ -22,7 +22,8 @@ The API is the board as its members see it: the people, the projects, and in eac
22
22
  | 400 | `project.invalid_address` | The skills address is not one, as the standard spells them. |
23
23
  | 400 | `project.invalid_icon` | The image for the mark is not a PNG, a JPEG, a GIF or a WebP, by its first bytes. |
24
24
  | 404 | `project.no_icon` | The project has no image for its mark. |
25
- | 400 | `member.invalid_person` | The person to list is not one of the workspace. |
25
+ | 400 | `member.invalid_person` | The person to list is not one of the workspace, or is deactivated. |
26
+ | 400 | `listing.unknown_host` | The login to let in names a provider nobody signs in through here. |
26
27
  | 400 | `task.invalid_assignee` | The assignee is not a person who may work in the project. |
27
28
  | 400 | `task.invalid_parent` | The parent is not a task of the project, is the task itself, or would make a loop. |
28
29
  | 400 | `task.invalid_category` | No category of the workspace has that key. |
@@ -42,6 +43,7 @@ The API is the board as its members see it: the people, the projects, and in eac
42
43
  | 404 | `project.not_found` | No project has that key, or it is not the asker's to see: the two are one answer. The key is checked before anything is asked. |
43
44
  | 404 | `task.not_found`, `decision.not_found`, `goal.not_found`, `token.not_found`, `person.not_found`, `run.not_found`, `run.task_not_found`, `member.not_found` | No such id in the project (or in the workspace, for a token, a person); for a token, none of the asker's. An id that is not a UUID is not found either, except a task's number. |
44
45
  | 404 | `category.not_found` | No category of the workspace has that key; a key that is not one is not found either. |
46
+ | 404 | `listing.not_found` | No login let in and not signed in with yet has that id; one somebody signed in with is the person's, and goes with their deactivation. |
45
47
  | 404 | `file.not_found` | No file handed in, or attached to the page, has that id in the project; a link handed in is not a file. |
46
48
  | 404 | `document.not_found`, `document.version_not_found` | No page has that path in the project, or the page has no such version. A path that is not one is not found either. |
47
49
  | 404 | `connect.not_found` | No agent asks to connect under this code or secret: it was never asked, it expired, the person said no, or the token was handed over already. |
@@ -56,7 +58,9 @@ The API is the board as its members see it: the people, the projects, and in eac
56
58
  | 409 | `token.too_many` | The person holds as many live tokens as one may (`MAX_TOKENS_PER_PERSON`). |
57
59
  | 409 | `connect.approved` | The connection was approved already; the command claims its token. |
58
60
  | 429 | `connect.too_many` | As many agents ask to connect as the console holds at once; try again in a few minutes. |
59
- | 409 | `person.last_admin` | The change would leave the board without an administrator. |
61
+ | 409 | `person.last_admin` | The change would leave the board without an administrator in. |
62
+ | 409 | `person.of_organization` | The organization let the person in, and says whether they are in; an administrator lists their login to keep one who left ([ADR-0022](../adr/0022-who-is-in-is-the-consoles-own-record-and-an-administrator-keeps-it.md)). |
63
+ | 409 | `listing.exists` | The login is let in already, or is one an active person signs in as. |
60
64
  | 409 | `run.over`, `run.task_closed` | The run has ended already; the task is done or dropped. A run open on a task is no refusal: a new run takes it over ([ADR-0020](../adr/0020-the-console-does-not-claim-an-agent-is-at-work-a-run-says-when-it-was-last-heard-from-and-a-new-run-takes-over.md)). |
61
65
  | 413 | `request.too_large` | The body is over the limit; for a file handed in or attached, the file is over `MAX_FILE_BYTES`. |
62
66
  | 503 | `file.store_unavailable` | The bytes of files are kept in a bucket, and it did not answer or refused the console; `retry-after` says when to try again. Nothing was written on the run or the page. |
@@ -65,15 +69,19 @@ The API is the board as its members see it: the people, the projects, and in eac
65
69
 
66
70
  ### `GET /api/v1/me`
67
71
 
68
- `{ "workspace": { "name", "tokenDaysAtMost" }, "person": ... | null, "agent": "..." | null, "language": "..." | null, "signIn": [{ "key", "label" }, ...] }`: what the board is called and the most days a token may be good for here (or `null` where a person chooses), who the session cookie or the token says is asking (`id`, `login`, `name` or `null`, `avatar` or `null`, `role`), with what (`agent`: the name of the token when a token asks, as its person called it, so that a console of a person's own knows it holds one and offers nothing a token cannot do; `null` on a session), the language the person chose for the pages (`language`, a tag, or `null` for the browser's), and the identity providers people sign in through (`gh`, `google`, each with the label of its button), none where nobody can. Nobody is an answer, not an error; the pages ask this once to decide what to show, and the command once, at `login`, to see that the console knows the token.
72
+ `{ "workspace": { "name", "tokenDaysAtMost", "skills": { "source", "address" } }, "person": ... | null, "agent": "..." | null, "language": "..." | null, "signIn": [{ "key", "label" }, ...] }`: what the board is called, the most days a token may be good for here (or `null` where a person chooses), where the organization's skills come from (`source`, the origin of the SkillCDN deployment they are read through, and `address`, the organization's, canonical, which a project without one of its own reads, or `null`), who the session cookie or the token says is asking (`id`, `login`, `name` or `null`, `avatar` or `null`, `role`), with what (`agent`: the name of the token when a token asks, as its person called it, so that a console of a person's own knows it holds one and offers nothing a token cannot do; `null` on a session), the language the person chose for the pages (`language`, a tag, or `null` for the browser's), and the identity providers people sign in through (`gh`, `google`, each with the label of its button), none where nobody can. Nobody is an answer, not an error; the pages ask this once to decide what to show, and the command once, at `login`, to see that the console knows the token.
69
73
 
70
74
  ### `GET /api/v1/people`
71
75
 
72
- `{ "items": [person, ...] }`: everyone who has signed in and is still listed, by login. What a picker of assignees and of members is made of. A person carries their `role` in the workspace: `admin`, who configures it, or `member`, who works in the projects they are in. A token reads it as its person does: what the command's `--assignee`, `member` and `person role` take a login from.
76
+ `{ "items": [person, ...], "listed": [listing, ...] }`: everyone who has signed in, those in first and by login, and the logins an administrator let in that nobody has signed in with yet ([ADR-0022](../adr/0022-who-is-in-is-the-consoles-own-record-and-an-administrator-keeps-it.md)). A person carries their `role` in the workspace (`admin`, who configures it, or `member`, who works in the projects they are in), their `status` (`active`, or `deactivated`: kept with everything they did, refused on every request, and offered to no picker), their `source` (what let them in at their last sign-in: `organization`, the git host's organization the deployment names; `domain`, the Workspace domain it names; or `listed`, an administrator's listing) and `deactivatedAt` (or `null`). A listing carries its `id`, the `host` (`gh`, `google`), the `login` as the administrator spelled it, and `createdAt`. `organization` is the organization at the git host whose members are in, where the deployment names one (`host`, `name`, and `syncedAt`, when the worker last read it whole, or `null` until it has), or `null`. What a picker of assignees and of members is made of, the active people. A token reads it as its person does: what the command's `--assignee`, `member` and `person` take a login from.
73
77
 
74
78
  ### `PATCH /api/v1/people/<id>`
75
79
 
76
- Takes `role` and answers the person. For an administrator, signed in or through their agent's token ([ADR-0021](../adr/0021-a-token-configures-as-its-person-does.md)). The board keeps at least one administrator (`person.last_admin`). A change writes a `person.role_changed` event with `login` and `role`; a change to what is already so writes nothing.
80
+ Takes `role`, `status`, or both, and answers the person. For an administrator, signed in or through their agent's token ([ADR-0021](../adr/0021-a-token-configures-as-its-person-does.md)). The board keeps at least one administrator in (`person.last_admin`). A change of role writes `person.role_changed` with `login` and `role`. `status: "deactivated"` takes the person out: refused on every request from the next one, their agents' tokens with them, listed nowhere and offered to no picker, kept with everything they did; the listing they came in on goes with it, so that signing in again admits nobody. `status: "active"` takes them back in, and lists them again where a listing let them in. Each writes `person.deactivated` or `person.reactivated` with `login`; what is already so writes nothing. A person the organization let in is neither (`person.of_organization`): the organization says, on the schedule the worker reads it on.
81
+
82
+ ### `POST /api/v1/listings` and `DELETE /api/v1/listings/<id>`
83
+
84
+ Who may sign in, by login ([ADR-0022](../adr/0022-who-is-in-is-the-consoles-own-record-and-an-administrator-keeps-it.md)): for an administrator, signed in or through their agent's token. `POST` takes `host` (one the deployment signs people in through; `listing.unknown_host` otherwise) and `login` (a login at the git host, or an address at Google, as the host spells one; trimmed, compared without regard to case), answers `201` with the listing, and writes `person.listed` with `login`. Whoever signs in with that account at that host is a person from then on, and the listing is theirs: bound to the account, so that a rename changes nothing and no other account can take the login. A login listed already, or one an active person signs in as, is `listing.exists`; a deactivated person's login may be listed, and they are back in, as listed, when they next sign in. `DELETE` takes a listing away that nobody has signed in with yet, answers `204` and writes `person.unlisted`; one somebody signed in with is `listing.not_found`, since it goes with the person's deactivation.
77
85
 
78
86
  ### `GET /api/v1/projects`
79
87
 
@@ -85,7 +93,7 @@ Takes `key` and `name`, and optionally `description`, `visibility` (default `pri
85
93
 
86
94
  ### `GET /api/v1/events?after=&limit=`
87
95
 
88
- The workspace's own events, the ones about no project: who joined (`person.joined`), who was made what (`person.role_changed`), and what became of the categories (`category.created`, `category.updated`, `category.removed`, each with the `key` and the `name`). The same shape and parameters as a project's feed below, without the filters.
96
+ The workspace's own events, the ones about no project: who joined (`person.joined`), who was made what (`person.role_changed`), who was let in, taken off the list, taken out and taken back in (`person.listed`, `person.unlisted`, `person.deactivated`, `person.reactivated`, each with the `login`), and what became of the categories (`category.created`, `category.updated`, `category.removed`, each with the `key` and the `name`). The same shape and parameters as a project's feed below, without the filters.
89
97
 
90
98
  ### `PATCH /api/v1/me`
91
99
 
@@ -99,6 +107,10 @@ Keeps the person's own choice of language for the pages ([ADR-0012](../adr/0012-
99
107
 
100
108
  Kept by an administrator, signed in or through their agent's token. `POST` takes `key`, `name` and optionally `color` (default `gray`), answers `201` with the category and writes a `category.created` event in the workspace's own feed with `key` and `name`; a key taken is `category.key_taken`, and the workspace holds at most `MAX_CATEGORIES` (`category.too_many`). `PATCH` takes any of `name` and `color`, answers the category and writes `category.updated` naming the `fields`; what is already so writes nothing; the key does not change. `DELETE` answers `204` and writes `category.removed`; a category tasks are sorted into is `category.in_use` until they are moved out of it.
101
109
 
110
+ ### `GET /api/v1/rules`, `PUT /api/v1/rules`, `POST /api/v1/rules/archive` and `GET /api/v1/rules/versions`
111
+
112
+ The rules of the board ([ADR-0023](../adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)): what the organization asks of agents, read by whoever is signed in or presents a token, kept by an administrator, signed in or through their agent's token. `GET` answers `{ "source", "body", "page" }`: `source` is `reference` while the organization has written none, and `body` is then the console's own rules as this version of the console carries them, with `page: null`; once written, `source` is `written`, `body` the page's and `page` the page without its body (as a folder lists one: `path` `rules`, `title` `Rules`, `version`, `updatedBy`, `agent`, `createdAt`, `updatedAt`). `PUT` takes `body` (Markdown, `MAX_RULES_LENGTH`) and optionally `baseVersion`, writes the next version of the page, bringing it back when it was put away, and answers what `GET` answers; the console's own rules sent as they are are never written, so that what holds keeps following the console's version: with none written they change nothing, and with the organization's written they put its page away, as `POST .../archive` does; a write from a version the rules have moved on from is `document.conflict`. The write is a `document.written` event in the workspace's own feed, with `path`, `title` and `version`. `POST .../archive` puts the written rules away, so that the console's own hold again (`document.archived`); what is put away already changes nothing. `.../versions` answers `{ "items": [version, ...] }` as a page's versions are answered, newest first, and `{ "items": [] }` while none is written. A body may say `{language}` for the language of the person an agent works for: the API answers the text as written, and the pages and the command fill it (`fillRules`), with the name of the language the person chose (`GET /api/v1/me`, `language`) or with the task's when they chose none.
113
+
102
114
  ### `GET /api/v1/work`
103
115
 
104
116
  `{ "tasks": [{ "project": { "key", "name", "color", "symbol", "icon" }, "task" }, ...], "decisions": [{ "project", "decision" }, ...] }`: what is on the asker's plate across the projects they may see ([ADR-0019](../adr/0019-a-task-is-planned-in-days-the-board-keeps-its-moments-and-goals-and-categories-give-the-work-its-shape.md)): the open tasks assigned to them, the sooner due first and those with no day last, and the decisions that wait for a person, the longest waiting first; each with the project it belongs to, so that a page says and links it. At most `LIST_LIMIT` of each.
@@ -111,10 +123,18 @@ The tokens of whoever is signed in, for their agents, scripts and consoles of th
111
123
 
112
124
  Takes one of the asker's tokens away, whoever holds it, and answers `204`. A token that is not the asker's is `token.not_found`.
113
125
 
126
+ ### `DELETE /api/v1/me/token`
127
+
128
+ The token the request is made with gives itself up, so that it is good for nothing from now on, and the answer is `204`: what `console logout` does, so that a token forgotten on a machine does not outlive it. The one thing a token does about the tokens; with a session, which has none to give, it is `request.invalid`.
129
+
114
130
  ### `GET /api/v1/people/<id>/tokens` and `DELETE /api/v1/people/<id>/tokens/<token id>`
115
131
 
116
132
  An administrator's sight of everyone's agents ([ADR-0011](../adr/0011-an-agent-connects-with-a-short-code-a-person-approves-and-the-token-is-never-shown.md)): the live tokens of any person, as `GET /api/v1/tokens` lists one's own, and the way to take one away, from the console's own pages; `auth.forbidden` for a member, `person.not_found` for an id that is nobody's, `token.not_found` for a token that is not that person's.
117
133
 
134
+ ### `GET /api/v1/people/<id>/work`
135
+
136
+ `{ "tasks": [{ "project", "task" }, ...] }`: what is on another person's plate, for whoever oversees them: an administrator, or an owner of a project the person is in (everyone of the workspace is in a project open to it; a private one holds those listed), signed in or through their agent. The person's open tasks, the sooner due first and those with no day last, within the projects the asker may see and no other, each with its project; the decisions are left out, since they wait for anyone. `auth.forbidden` for anyone else; `person.not_found` for an id that is nobody's.
137
+
118
138
  ### Connecting an agent
119
139
 
120
140
  `POST /api/v1/connect`, `GET /api/v1/connect/<code>`, `POST /api/v1/connect/<code>/approve`, `POST /api/v1/connect/<code>/deny` and `POST /api/v1/connect/claim`: how an agent gets its token without anyone copying one ([ADR-0011](../adr/0011-an-agent-connects-with-a-short-code-a-person-approves-and-the-token-is-never-shown.md)).
@@ -209,9 +229,13 @@ Takes `status` (`finished`, `failed` or `abandoned`) and optionally a `summary`
209
229
 
210
230
  The project's skills, as the SkillCDN deployment serves them at the project's address, or at the organization's (`SKILLS_ADDRESS`) when the project names none, read through `SKILLCDN_URL`: `{ "address", "source", "page", "status", "items" }`. `address` is canonical, or `null` with `status: "none"` when neither names one; `source` is the deployment's origin and `page` where a person browses the address. `status` is `ready`, or why `items` is empty: `indexing` and `failed` as the deployment says of the repository, `not_found` when it does not serve the address to the console (which asks as nobody, so a private repository is not read), `unavailable` when it could not be reached or read. An item is one skill: `name`, `description`, `directory` and `path` (of its `SKILL.md`, from the repository's root), `page` (the skill at the deployment, for a person), `uri` (what an agent loads it by through its own SkillCDN connection, `skill://gh/<owner>/<repo>/<path>`, or `null`), and `translations` (the title and the description by language tag, as the repository gives them). The console keeps nothing of the skills: one answer per address stands for a minute, then the deployment is asked again.
211
231
 
232
+ ### `GET /api/v1/projects/<key>/rules`
233
+
234
+ `{ "workspace": rules, "project": rules }`: the rules that hold in the project ([ADR-0023](../adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)), for whoever may see it, each half shaped as `GET /api/v1/rules` answers: the workspace's, and the project's own, whose `source` is `written`, with its `body` and its `page`, or `none`, with `body` and `page` `null`, when the project adds nothing to the workspace's. A project's rules are the page `rules` of its documents, written and put away through the routes below.
235
+
212
236
  ### The documents
213
237
 
214
- The project's pages of Markdown ([ADR-0009](../adr/0009-documents-are-pages-of-markdown-in-a-project-addressed-by-path-versioned-and-linked-both-ways.md)): each under a path of lowercase segments separated by slashes (`guides/onboarding`), which is its address and does not change; the folders are what the paths say. In every path below, the document's path is **one segment of the URL, its slashes encoded** (`/docs/guides%2Fonboarding`), which is what `projectPath(key, "docs", path)` builds. Whoever may see the project reads them; whoever may work in it writes them, with a session or a token.
238
+ The project's pages of Markdown ([ADR-0009](../adr/0009-documents-are-pages-of-markdown-in-a-project-addressed-by-path-versioned-and-linked-both-ways.md)): each under a path of lowercase segments separated by slashes (`guides/onboarding`), which is its address and does not change; the folders are what the paths say. In every path below, the document's path is **one segment of the URL, its slashes encoded** (`/docs/guides%2Fonboarding`), which is what `projectPath(key, "docs", path)` builds. Whoever may see the project reads them; whoever may work in it writes them, with a session or a token. The page `rules` is the project's rules ([ADR-0023](../adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)): written, put away, brought back and given files by an owner alone (`auth.forbidden` otherwise), kept to `MAX_RULES_LENGTH` (`request.invalid`), with the one title `Rules` whatever was sent, written again when it was put away, and in no folder and no search, since it is the project's configuration; it is read at its path as any page is.
215
239
 
216
240
  #### `GET /api/v1/projects/<key>/docs?folder=&q=&archived=`
217
241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillcdn/console",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "What a custom SkillCDN console is built from: the API client and schemas, the components, the composition of the default console, and the console command agents work the board with.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/skillcdn/console#readme",
@@ -74,7 +74,7 @@ Produces the **pages**. For a page the default console lacks: `useConsoleData(cl
74
74
 
75
75
  ### Phase 4: Run it against the board
76
76
 
77
- Produces the **running console**. `console serve` serves the API at `http://127.0.0.1:11197/api/` while `npx vite` serves the pages, and `console serve dist` serves the build whole at `http://127.0.0.1:11197/`. The pages hold no token; the command carries it, on the loopback only. The pages know they hold a token (`GET /api/v1/me` answers `agent`) and offer nothing a token cannot do: the tokens themselves stay on the organization's console, and everything else, configuring included, the pages do on the token as the person ([ADR-0021](/docs/adr/0021-a-token-configures-as-its-person-does.md)). The organization's console is looked at the same way, on the builder's token: it shows every page a token may see, and the pages a token may not (the agents) are the package's own and unchanged, so the look checkpoint covers everything the console changed. Where the organization's build then goes is the plan's answer: `console-ui/` of the deployment repository, whose workflow builds it into the image on every push, handed over to deploying-a-console, the skill beside this one at the same address (in the package under `node_modules/@skillcdn/console/skills/deploying-a-console/`), with the source and the repository, and with the package pinned at the version of the release the deployment pins as `CONSOLE_REF` (the tag `@skillcdn/console@<version>`), so that the pages and the server are one release and move together; the build beside the Dockerfile of [deploy/README.md](/deploy/README.md) "A custom console in the image", for an image the organization builds itself; or the mounted directory. A script: `createClient({ baseUrl, token })`, every answer parsed with the package's schemas; it configures as its person does too, with `createProject`, `updatePerson`, a project's `update`, `setIcon`, `addMember`, `updateMember` and `removeMember`, and `createCategory`, `updateCategory` and `removeCategory`, refused with `auth.forbidden` where the person may not, and never the tokens.
77
+ Produces the **running console**. `console serve` serves the API at `http://127.0.0.1:11197/api/` while `npx vite` serves the pages, and `console serve dist` serves the build whole at `http://127.0.0.1:11197/`. The pages hold no token; the command carries it, on the loopback only. The pages know they hold a token (`GET /api/v1/me` answers `agent`) and offer nothing a token cannot do: the tokens themselves stay on the organization's console, and everything else, configuring included, the pages do on the token as the person ([ADR-0021](/docs/adr/0021-a-token-configures-as-its-person-does.md)). The organization's console is looked at the same way, on the builder's token: it shows every page a token may see, and the pages a token may not (the agents) are the package's own and unchanged, so the look checkpoint covers everything the console changed. Where the organization's build then goes is the plan's answer: `console-ui/` of the deployment repository, whose workflow builds it into the image on every push, handed over to deploying-a-console, the skill beside this one at the same address (in the package under `node_modules/@skillcdn/console/skills/deploying-a-console/`), with the source and the repository, and with the package pinned at the version of the release the deployment pins as `CONSOLE_REF` (the tag `@skillcdn/console@<version>`), so that the pages and the server are one release and move together; the build beside the Dockerfile of [deploy/README.md](/deploy/README.md) "A custom console in the image", for an image the organization builds itself; or the mounted directory. A script: `createClient({ baseUrl, token })`, every answer parsed with the package's schemas; it configures as its person does too, with `createProject`, `updatePerson`, a project's `update`, `setIcon`, `addMember`, `updateMember` and `removeMember`, `createCategory`, `updateCategory` and `removeCategory`, and the rules of the board with `writeRules` and `archiveRules` and a project's as the page `rules` ([ADR-0023](/docs/adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)), refused with `auth.forbidden` where the person may not, and never the tokens.
78
78
 
79
79
  ### Phase 5: Check and show
80
80
 
@@ -33,7 +33,7 @@ What goes in: an AWS account, a domain on Cloudflare or one to buy, and the answ
33
33
  | The deployer's access key and the Cloudflare token, as [access.md](references/access.md) says they are made and reach the agent | Everything on AWS and at Cloudflare |
34
34
  | The `gh` command signed in (`gh auth status`), or an empty private repository the person made | The deployment repository, its first push, watching its runs |
35
35
  | The `console` command, `npm install -g @skillcdn/console` in phase 1 | The proof at the end: an agent connected, a file handed in; and this skill's two scripts, which the package carries at `$(npm root -g)/@skillcdn/console/skills/deploying-a-console/scripts/`, copied into the run's `scratch/` folder, or read through the connection and written there |
36
- | The person, with a browser on any device | The OAuth app, the first sign-in, approving the agent's code, a registrar's nameservers |
36
+ | The person, with a browser on any device | The GitHub App or the Google client, the first sign-in, approving the agent's code, a registrar's nameservers |
37
37
  | Network access to AWS, Cloudflare, GitHub and npm | |
38
38
 
39
39
  Check these before the first message. Without the AWS CLI, offer to install it (access.md); without `gh`, the person makes the repository; without network, stop. This skill's own pages ([access.md](references/access.md), [sizing.md](references/sizing.md), [resources.md](references/resources.md)) arrive with it through SkillCDN, in the package, and in a copy of its directory. `deploy/README.md` and the decisions are read through the repository connection or in a checkout of the console's repository; without them, this skill and its pages carry the shape.
@@ -45,7 +45,7 @@ Check these before the first message. Without the AWS CLI, offer to install it (
45
45
  | How many people | Asked: "How many people will use the console within a year: just you, up to 10, up to 30, or up to 100?" The answer picks the size ([sizing.md](references/sizing.md)). |
46
46
  | The board's name | Asked, with the organization's name as the suggestion when the request gives one: "What should the board be called? Usually the organization's name." |
47
47
  | The web address | Asked: "Which web address should the console have? A domain you already own, and where it is registered (I set it up on Cloudflare; you change its nameservers there once, and I give you the steps), or should I find one to buy (I show the price before buying)? I suggest `console.<domain>`." A domain is needed: the tunnel has no free hostname. A domain that already serves the organization's site is fine: only the console's hostname is added to its zone, and nothing of the site is touched (resources.md "A zone that serves other hosts"). |
48
- | How people sign in, and who | Asked: "How should people sign in: with GitHub, with Google (Workspace), or both? Who is in: everyone's GitHub login or Google address, and who among them configures the console (you, at least)? With a Google Workspace, everyone of the domain can be in." |
48
+ | How people sign in, and who | Asked: "How should people sign in: with GitHub, with Google (Workspace), or both? Who configures the console (you, at least): their GitHub login or Google address. With GitHub, everyone of your organization can be in, as the organization has them: say which organization. With a Google Workspace, everyone of the domain is in. Anyone else, an administrator lets in on the People page once the console runs." |
49
49
  | The organization's skills | Asked: "Where are your organization's skills on SkillCDN, if anywhere yet? An address like `/gh/<owner>/<repo>`." Default: none; a project names one later on its Settings page. |
50
50
  | The AWS account | Asked: "Do you have an AWS account for this, or should the console get an account of its own (the simplest to run and to read the bill of)?" A new account is made by the person, on the paid plan, with the order of cost already in front of them (the second message). |
51
51
  | The region | Asked when the organization's country does not say: "Which AWS region: the one nearest your people?" Default: the nearest to where the organization is (`ap-northeast-2`, Seoul, for Korea; `ap-northeast-1` for Japan; `eu-central-1` for central Europe; `us-east-1` for the eastern United States). |
@@ -69,7 +69,7 @@ Produces the **plan**, shown at the checkpoint. From the answers: the size and w
69
69
 
70
70
  ### Phase 3: Foundation
71
71
 
72
- Produces the **resource record**: each resource with its name and id. In this order: the zone at Cloudflare, with the records the domain serves already found by Cloudflare's scan and checked by the person against their registrar's DNS page, so that nameservers propagate meanwhile; the network and its two security groups; the database, started, and waited for while the rest is made; the bucket; the image repository, the log group, the roles, the task's with the bucket's policy, the cluster; the tunnel, the hostname, always-HTTPS for the hostname and the rate limiting rule; the parameters, generated and derived, from the secrets file. Then, the hostname being known, the message for each secret the person holds (access.md "The OAuth app", "The OAuth client"): "Save it in the secrets file as the line I show, or say `later` and that way of signing in stays off until it is set." A value the person pastes into the chat instead is written into the file by the agent's file tool, never repeated, and the person is told to generate a new one once the run is over, since the chat kept a copy; the new one goes in as "a secret rotated" of the record.
72
+ Produces the **resource record**: each resource with its name and id. In this order: the zone at Cloudflare, with the records the domain serves already found by Cloudflare's scan and checked by the person against their registrar's DNS page, so that nameservers propagate meanwhile; the network and its two security groups; the database, started, and waited for while the rest is made; the bucket; the image repository, the log group, the roles, the task's with the bucket's policy, the cluster; the tunnel, the hostname, always-HTTPS for the hostname and the rate limiting rule; the parameters, generated and derived, from the secrets file. Then, the hostname being known, the message for each secret the person holds (access.md "The GitHub App", "The OAuth client"): "Save it in the secrets file as the line I show, or say `later` and that way of signing in stays off until it is set." A value the person pastes into the chat instead is written into the file by the agent's file tool, never repeated, and the person is told to generate a new one once the run is over, since the chat kept a copy; the new one goes in as "a secret rotated" of the record.
73
73
 
74
74
  ### Phase 4: The deployment repository
75
75
 
@@ -93,7 +93,7 @@ Produces **`DEPLOY.md`** in the repository, from the template in resources.md: w
93
93
 
94
94
  ### Running it again
95
95
 
96
- The same skill, from phase 2, with the plan naming only what changes: a new version (the next release tag's commit as `CONSOLE_REF` in `deploy/console.env`, with `console-ui/` moved to the same version of the package when there is one, a push), a new connector (`CLOUDFLARED_VERSION` there, a push), the next size (the numbers in the task definitions and a push; the database's class with one command, as sizing.md "Growing" says), a member added or removed (`MEMBERS` and `ADMINS` in `deploy/api.task.json`, a push), a secret rotated (the parameter overwritten, the service rolled), the console paused or removed (resources.md "Removing"). Each is confirmed at the plan, and the record is updated with it.
96
+ The same skill, from phase 2, with the plan naming only what changes: a new version (the next release tag's commit as `CONSOLE_REF` in `deploy/console.env`, with `console-ui/` moved to the same version of the package when there is one, a push), a new connector (`CLOUDFLARED_VERSION` there, a push), the next size (the numbers in the task definitions and a push; the database's class with one command, as sizing.md "Growing" says), a person let in or taken out (on the People page, or `console person add <login>` and `console person deactivate <login>`, by an administrator; no push), a secret rotated (the parameter overwritten, the service rolled), the console paused or removed (resources.md "Removing"). Each is confirmed at the plan, and the record is updated with it.
97
97
 
98
98
  ### Verdicts
99
99
 
@@ -109,7 +109,7 @@ The same skill, from phase 2, with the plan naming only what changes: a new vers
109
109
  1. The access key, the token and every secret stay out of the repository, the logs, the chat and the agent's own words: a value is read from its file into the environment or the parameter store, never put as a literal on a command line, never echoed; a value the person pasted is written to its file with a file tool and the person is told to make a new one when the run is over; the secrets file is deleted, on the person's word, when its values are stored. A leak means a rotation, which the person is told at once.
110
110
  2. Nothing is bought or made before the price is in front of the person and they said the word: the second message carries the order of cost, the plan carries today's estimate of everything that bills; a domain is bought only after its price is shown.
111
111
  3. The first push is confirmed, and every push after it: once the repository is connected, a push is a deployment, which the person chose at the plan.
112
- 4. The person is never asked to do what the key and the token can do; what only they can do (an OAuth app, a sign-in, approving a code, nameservers at their registrar) is given as the exact steps of the day in one message, for the registrar they named where its steps are known and in general words otherwise, so that they can do it while the run goes on.
112
+ 4. The person is never asked to do what the key and the token can do; what only they can do (a GitHub App or a Google client, a sign-in, approving a code, nameservers at their registrar) is given as the exact steps of the day in one message, for the registrar they named where its steps are known and in general words otherwise, so that they can do it while the run goes on.
113
113
  5. Nothing of the deployment listens on the internet: the tasks' security group has no inbound rule, the database is not publicly accessible, the bucket blocks public access, and the hostname reaches the console only through the tunnel.
114
114
  6. Names and ids go into the repository and the record; a value a secret scanner would flag never does, and `scratch/`, the key file and the token file never enter git. Every file the repository gets is shown before it is pushed.
115
115
  7. What was created is kept and recorded, never silently deleted; removing the deployment is a run of its own, asked for, and confirmed resource by resource.
@@ -4,7 +4,8 @@
4
4
  "DATABASE_URL": "derived: postgres://console:<generated password>@<database endpoint>:5432/console",
5
5
  "DATABASE_CA": "derived: the regional certificate bundle of the database service, as PEM",
6
6
  "TUNNEL_TOKEN": "derived: the connector token of the tunnel",
7
- "GITHUB_CLIENT_SECRET": "asked: the client secret of the OAuth app, or later",
7
+ "GITHUB_CLIENT_SECRET": "asked: the client secret of the GitHub App (or of an OAuth app), or later",
8
+ "GITHUB_APP_PRIVATE_KEY": "asked, with an organization: the private key of the GitHub App, as PEM, its lines joined with \\n; or later",
8
9
  "GOOGLE_CLIENT_SECRET": "asked: the client secret of the OAuth client, or later",
9
10
  "S3_ACCESS_KEY_ID": "only with the bucket on R2 (sizing.md, Options): asked, the key made in the Cloudflare dashboard",
10
11
  "S3_SECRET_ACCESS_KEY": "only with the bucket on R2: its secret"
@@ -63,14 +63,18 @@ curl -s https://api.cloudflare.com/client/v4/accounts -H "Authorization: Bearer
63
63
 
64
64
  **The deployment repository.** The organization's deployment lives in a private repository on GitHub: the task definitions, the workflow that builds and deploys, the record. The agent makes it with the `gh` command signed in (`gh auth status`; `gh auth login` otherwise, which opens the browser for the person) under the owner the person names: their account, or an organization. Without `gh`, the person creates an empty private repository in the browser (New repository, private, no README) and gives its address, and the agent pushes to it.
65
65
 
66
- **The OAuth app, for signing in with GitHub.** Once the console's address is known, the person, signed in to GitHub (checked 2026-10): Settings (under the avatar), Developer settings, OAuth Apps, New OAuth App (Register a new application, the first time).
66
+ **The GitHub App, for signing in with GitHub, and for the organization to say who is in.** One app does both ([ADR-0022](/docs/adr/0022-who-is-in-is-the-consoles-own-record-and-an-administrator-keeps-it.md)): its client signs people in, and, installed on the organization, it lets the console read who is a member, at sign-in and every ten minutes after. Once the console's address is known, the person, signed in to GitHub as an owner of the organization (checked 2026-10): Your organizations, Settings next to the organization, Developer settings, GitHub Apps, New GitHub App.
67
67
 
68
- - Application name: the board's name.
68
+ - GitHub App name: the board's name (34 characters at most, unique across GitHub).
69
69
  - Homepage URL: the console's address, `https://<hostname>`.
70
- - Authorization callback URL: `https://<hostname>/auth/gh/callback`.
71
- - Register application. Copy the **Client ID** into the chat (it is not secret). Generate a new client secret, and save it to the secrets file as `GITHUB_CLIENT_SECRET` (below), as the line the agent shows. A secret pasted into the chat instead is written into the file by the agent's file tool and never repeated, and the person generates a new one once the run is over, since the chat kept a copy; the new one goes in as "a secret rotated" of the record.
72
-
73
- An organization-owned app is the same form under the organization's settings, Developer settings. No scopes are needed: the console asks only who the person is.
70
+ - Callback URL: `https://<hostname>/auth/gh/callback`. Leave "Expire user authorization tokens" as it is, and "Request user authorization (OAuth) during installation" off: the console asks who the person is once, and keeps nothing of the credential.
71
+ - Webhook: untick Active. The console takes no webhooks.
72
+ - Permissions: under Organization permissions, Members: Read-only. Nothing else, and no repository permission: the console reads who is in, and nothing of the code.
73
+ - Where can this GitHub App be installed?: Only on this account.
74
+ - Create GitHub App. The app's page shows the **App ID** and the **Client ID**: copy both into the chat (neither is secret). Under Client secrets, Generate a new client secret, and save it to the secrets file as `GITHUB_CLIENT_SECRET` (below), as the line the agent shows. Under Private keys, Generate a private key: a `.pem` file downloads; save its content to the secrets file as `GITHUB_APP_PRIVATE_KEY`, the file's lines joined with `\n`, as the line the agent shows (the agent writes it from the file when told where it is, and deletes the file on the person's word). A secret pasted into the chat instead is written into the file by the agent's file tool and never repeated, and the person generates a new one once the run is over, since the chat kept a copy; the new one goes in as "a secret rotated" of the record.
75
+ - Install App, in the app's left sidebar: Install next to the organization, and confirm. No repository access is asked for, since the app has no repository permission. Everyone of the organization is in from then on, as the organization has them; the plan's `GITHUB_ORG` is the organization's login, as it reads in `github.com/<login>`.
76
+
77
+ Without an organization, an OAuth app signs people in as well (Developer settings, OAuth Apps, New OAuth App: the same name, homepage and callback; Register application; the Client ID and a client secret), and an administrator lets each person in on the People page. No scopes are needed either way: the console asks only who the person is.
74
78
 
75
79
  **The OAuth client, for signing in with Google.** In the Google Cloud console, a project of the organization's, Google Auth Platform (checked 2026-10): if the project has not registered with Google Auth yet, the Overview asks for the app's name, a support address and the audience (Internal, for a Workspace organization), once. Then Clients, Create client, Application type **Web application**, name it, under Authorized redirect URIs add `https://<hostname>/auth/google/callback`, Create. Copy the **Client ID** into the chat; the client secret is shown once: save it to the secrets file as `GOOGLE_CLIENT_SECRET`, as the line the agent shows (pasted instead: written to the file by the agent, never repeated, and replaced after the run, as with GitHub's). The Workspace domain, when everyone of it is a member, is the plan's `GOOGLE_WORKSPACE_DOMAIN`. Changes take from minutes to hours to be effective at Google.
76
80
 
@@ -202,7 +202,7 @@ The generated one first, if the Conventions' example was not run as a step: `nod
202
202
 
203
203
  ### The secrets the person holds
204
204
 
205
- The hostname being known, one message per provider chosen with the steps of access.md "The OAuth app" and "The OAuth client", the exact URLs filled in, the line to add to the secrets file (`"GITHUB_CLIENT_SECRET": "<the secret>"`), and `later` as the other answer. On an answer, store it (`store` again adds what is new) and note the client id for the task definition. A provider answered `later` is left out of the task definition entirely, since the console wants both halves or neither; a provider not chosen has no line in the secrets file and nothing in the record.
205
+ The hostname being known, one message per provider chosen with the steps of access.md "The GitHub App" and "The OAuth client", the exact URLs filled in, the lines to add to the secrets file (`"GITHUB_CLIENT_SECRET": "<the secret>"`, and, with an organization, `"GITHUB_APP_PRIVATE_KEY": "<the key, as PEM>"`, the file's lines joined with `\n`), and `later` as the other answer. On an answer, store it (`store` again adds what is new) and note the client id, and the app's id and the organization, for the task definition. A provider answered `later` is left out of the task definition entirely, since the console wants both halves or neither, and so is the organization without its key, since it wants all three or none; a provider not chosen has no line in the secrets file and nothing in the record.
206
206
 
207
207
  ## Phase 4: The deployment repository
208
208
 
@@ -256,9 +256,10 @@ The task definition of the `api` role with the tunnel's connector beside it, in
256
256
  { "name": "TRUSTED_PROXIES", "value": "127.0.0.1,::1" },
257
257
  { "name": "CLIENT_IP_HEADER", "value": "cf-connecting-ip" },
258
258
  { "name": "HTTP_KEEP_ALIVE_SECONDS", "value": "100" },
259
- { "name": "MEMBERS", "value": "<logins and addresses, comma-separated>" },
260
- { "name": "ADMINS", "value": "<logins among them>" },
261
- { "name": "GITHUB_CLIENT_ID", "value": "<the OAuth app's client id>" },
259
+ { "name": "ADMINS", "value": "<the first administrators: logins and addresses, comma-separated>" },
260
+ { "name": "GITHUB_CLIENT_ID", "value": "<the GitHub App's client id>" },
261
+ { "name": "GITHUB_APP_ID", "value": "<the GitHub App's id, or drop the three lines of the organization>" },
262
+ { "name": "GITHUB_ORG", "value": "<the organization's login at GitHub>" },
262
263
  { "name": "SKILLS_ADDRESS", "value": "<the organization's skills address, or drop the line>" },
263
264
  { "name": "S3_ENDPOINT", "value": "https://s3.<region>.amazonaws.com" },
264
265
  { "name": "S3_BUCKET", "value": "console-files-<account>" },
@@ -269,7 +270,8 @@ The task definition of the `api` role with the tunnel's connector beside it, in
269
270
  { "name": "DATABASE_URL", "valueFrom": "arn:aws:ssm:<region>:<account>:parameter/console/DATABASE_URL" },
270
271
  { "name": "DATABASE_CA", "valueFrom": "arn:aws:ssm:<region>:<account>:parameter/console/DATABASE_CA" },
271
272
  { "name": "AUTH_SECRET", "valueFrom": "arn:aws:ssm:<region>:<account>:parameter/console/AUTH_SECRET" },
272
- { "name": "GITHUB_CLIENT_SECRET", "valueFrom": "arn:aws:ssm:<region>:<account>:parameter/console/GITHUB_CLIENT_SECRET" }
273
+ { "name": "GITHUB_CLIENT_SECRET", "valueFrom": "arn:aws:ssm:<region>:<account>:parameter/console/GITHUB_CLIENT_SECRET" },
274
+ { "name": "GITHUB_APP_PRIVATE_KEY", "valueFrom": "arn:aws:ssm:<region>:<account>:parameter/console/GITHUB_APP_PRIVATE_KEY" }
273
275
  ],
274
276
  "healthCheck": {
275
277
  "command": ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:11199/readyz').then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1))\""],
@@ -507,7 +509,7 @@ Made on <date> with the skill `deploying-a-console` of the SkillCDN Console (ski
507
509
 
508
510
  - **A deployment** is a push to `main` that touches `deploy/` or `console-ui/`: the workflow builds the image, runs the migrations, and rolls the services. `gh run list` shows the runs.
509
511
  - **A new version of the console:** set `CONSOLE_REF` in `deploy/console.env` to the commit of the newest release tag: the last line of `git ls-remote --tags https://github.com/skillcdn/console 'refs/tags/@skillcdn/console@*' | sort -t@ -k3 -V` is the highest version, with the commit in its first column; move `console-ui/` to the same version of the package when there is one; push. **A new connector:** `CLOUDFLARED_VERSION` there, push.
510
- - **A person added or removed:** `MEMBERS` and `ADMINS` in `deploy/api.task.json`, push. Administrators also change roles on the People page.
512
+ - **A person added or removed:** with an organization at GitHub (`GITHUB_ORG`), in the organization, which the console reads every ten minutes; otherwise on the People page, or with `console person add <login>` and `console person deactivate <login>`, by an administrator; nothing to push. With a Google Workspace, everyone of `GOOGLE_WORKSPACE_DOMAIN` is in. `ADMINS` in `deploy/api.task.json` names only the first administrators, who make others on the People page.
511
513
  - **The next size:** the numbers in `deploy/api.task.json` (and `deploy/worker.task.json` at `large`), `API_COUNT` and `WORKER_COUNT` in `deploy/console.env`, push; to `large`, also `deploy/worker.task.json` written as the skill's resources.md gives it and `WORKER_IN_PROCESS` dropped from the api task; the database: `aws rds modify-db-instance --db-instance-identifier console --db-instance-class <class> --apply-immediately` (a few minutes of unavailability).
512
514
  - **A secret rotated:** the new value into a secrets file of the same shape with the skill's script (`set`), then `node <the script> store <file> /console`, which overwrites the parameter in its tier (`$(npm root -g)/@skillcdn/console/skills/deploying-a-console/scripts/store-secrets.mjs`; `DATABASE_CA` is in the advanced tier, which an `aws ssm put-parameter --overwrite` by hand must name with `--tier Advanced`); then `aws ecs update-service --cluster console --service api --force-new-deployment`.
513
515
  - **The organization's own console:** its source in `console-ui/` (building-a-console makes it); a push builds it into the image.
@@ -551,7 +553,8 @@ Only on request, each step confirmed, in this order, after a last snapshot of th
551
553
  | `https://<hostname>` answers 530 or 502 from Cloudflare | No connector yet, or the hostname's ingress rule points elsewhere | Wait for the service; check the tunnel's configuration and the DNS record |
552
554
  | `https://<hostname>` does not resolve | The zone is not active yet | The nameservers at the registrar; `cf "/zones?name=<domain>"` says when |
553
555
  | The sign-in button is missing | The provider's id or secret is not in the task definition | Both halves or neither; check `environment` and `secrets` |
554
- | The sign-in is refused after the provider | The login is not in `MEMBERS` (or the domain not in `GOOGLE_WORKSPACE_DOMAIN`) | Add it, push |
556
+ | The sign-in is refused after the provider | Nobody let the login in: it is not in `ADMINS`, not of the organization (`GITHUB_ORG`) or of `GOOGLE_WORKSPACE_DOMAIN`, and no administrator listed it on the People page; or the person was deactivated | An administrator lets the login in on the People page (`console person add <login>`), or takes the person back in; the first administrator is `ADMINS`, a push |
557
+ | The log says `the organization could not be read` | The app's key is wrong (`unauthorized`), the app is not installed on the organization or lacks the Members permission (`invalid`, `unauthorized`), or GitHub was away (`transient`) | Check the parameter, the installation and the app's permissions; nothing changed meanwhile, and the next pass reads again |
555
558
  | The mirror step cannot pull `cloudflare/cloudflared` | Docker Hub's anonymous pull limit on the runner | Run the workflow again (`gh run rerun <id>`); the pull happens once per connector version, and the tasks pull from the repository afterwards |
556
559
  | `gh run watch` shows the build failing on `npm ci` in `console-ui` | The UI's lockfile is out of step | Fix in `console-ui/` (building-a-console), push |
557
560
  | A 524 at Cloudflare on a long read | A request held longer than the proxy's 100 seconds | The console holds a decision's read for 50 at most; look for a slow database |
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: working-the-board
3
- description: "Works a task from the board of a SkillCDN Console with the console command, as the person whose token the command holds: reads the task, takes it, reports at the milestones of the work, asks on the board when a person must decide and waits for the answer, hands in what was made as a link or a file, writes down what the next agent needs on a page of the project, and finishes. Use when an agent is told to take, work or finish a task on the console, or to report, ask, hand in or write a page there; any agent with a shell where the command is signed in. To build a console or a script against the console's API, use building-a-console; to deploy a console for an organization, use deploying-a-console."
3
+ description: "Works a task from the board of a SkillCDN Console with the console command, as the person whose token the command holds: reads the rules of the board and the task, takes it, reports at the milestones of the work, asks on the board when a person must decide and waits for the answer, hands in what was made as a link or a file, writes down what the next agent needs on a page of the project, and finishes. Use when an agent is told to take, work or finish a task on the console, or to report, ask, hand in or write a page there; any agent with a shell where the command is signed in. To build a console or a script against the console's API, use building-a-console; to deploy a console for an organization, use deploying-a-console."
4
4
  license: MIT
5
5
  compatibility: Needs a shell with the console command on the PATH (npm install -g @skillcdn/console, Node.js 24 or newer), signed in by a person. Nothing else; the command needs no key of its own and the agent never sees a token.
6
6
  metadata:
7
7
  author: skillcdn
8
- version: "1.3"
8
+ version: "1.5"
9
9
  skillcdn:
10
10
  translations:
11
11
  ko:
12
12
  title: 콘솔 보드에서 일하기
13
- description: "SkillCDN 콘솔의 보드에 있는 작업을 console 명령으로 수행합니다. 명령에 로그인한 사람의 자격으로, 작업을 읽고 맡고, 진행의 이정표마다 보고하고, 사람이 정해야 할 일은 보드에 물어 답을 기다리고, 만든 것을 링크나 파일로 제출하고, 다음 에이전트에게 필요한 것을 프로젝트 페이지에 적고, 마칩니다. 에이전트에게 콘솔의 작업을 맡거나 끝내라고, 또는 보고·질문·제출·페이지 쓰기를 하라고 할 때 쓰세요. 콘솔이나 API 클라이언트를 만들 때는 building-a-console을, 조직의 콘솔을 배포할 때는 deploying-a-console을 쓰세요."
13
+ description: "SkillCDN 콘솔의 보드에 있는 작업을 console 명령으로 수행합니다. 명령에 로그인한 사람의 자격으로, 보드의 규칙과 작업을 읽고 맡고, 진행의 이정표마다 보고하고, 사람이 정해야 할 일은 보드에 물어 답을 기다리고, 만든 것을 링크나 파일로 제출하고, 다음 에이전트에게 필요한 것을 프로젝트 페이지에 적고, 마칩니다. 에이전트에게 콘솔의 작업을 맡거나 끝내라고, 또는 보고·질문·제출·페이지 쓰기를 하라고 할 때 쓰세요. 콘솔이나 API 클라이언트를 만들 때는 building-a-console을, 조직의 콘솔을 배포할 때는 deploying-a-console을 쓰세요."
14
14
  ---
15
15
  # Working a task on the board
16
16
 
@@ -22,7 +22,7 @@ A task of the board goes in, named by its number; a run comes out: the task take
22
22
  - **Checkpoints:** on the board, as decisions (phase 4), which a person answers from wherever they are; the reports say what was done at each milestone, and need no answer.
23
23
  - **Go-ahead:** the task's body is the go-ahead. A task that says what the agent may decide alone is followed within that; everything else that would change scope, cost or a trade-off is a decision.
24
24
  - **Changes mid-run:** a person changes the task or answers a decision on the board; the run takes it from there and says so in its next report. A report is never rewritten.
25
- - **Language:** reports, questions, pages and summaries are in the language the task is written in, so that the people of the board read them as they wrote.
25
+ - **Language:** what people read, the reports, the questions, the pages and the summaries, is in the language the rules name for the person (`console take` prints them with the task), else the task's, so that the people of the board read as they wrote.
26
26
 
27
27
  ## Requirements
28
28
 
@@ -37,9 +37,9 @@ The full contract is the [specification of the command line](/docs/specs/cli.md)
37
37
 
38
38
  | Input | Source |
39
39
  |---|---|
40
- | The task | Its number (`#7`) or its id, from what the person said. Told to pick one, `console work` lists what is on the person's plate across their projects, the sooner due first, and `console tasks --state ready --mine` what is ready and theirs in this one (`--due overdue`, `--due week`, `--category <key>` and `--goal <id>` narrow it further); a task is never taken without being told which, or that any ready one may be. |
41
- | The work | The task's body, read with `console task <number>`: what to make, where, the milestones, what to ask; with its plan, the category, the goal it works towards (`console goal <id>` says what reaching it means) and the days it starts and is due, which the reports and the summary keep to. The pages it links to (`console doc <path>`) and the project's skills (`console skills`, each loaded through the agent's own SkillCDN connection) say the rest. |
42
- | The organization's way | Its own skill for its console, when it has one, adds which tasks to take, what to report and when to ask; it comes through the same kind of address as its other skills. |
40
+ | The task | Its number (`#7`) or its id, from what the person said. Told to pick one, `console work` lists what is on the person's plate across their projects, the sooner due first (`--person <login>` another person's, for an administrator or an owner of a project they are in), and `console tasks --state ready --mine` what is ready and theirs in this one (`--due overdue`, `--due week`, `--category <key>` and `--goal <id>` narrow it further); a task is never taken without being told which, or that any ready one may be. |
41
+ | The work | The task's body, read with `console task <number>`: what to make, where, the milestones, what to ask; with its plan, the category, the goal it works towards (`console goal <id>` says what reaching it means) and the days it starts and is due, which the reports and the summary keep to. The pages it links to (`console doc <path>`) and the project's skills (`console skills`, each loaded through the agent's own SkillCDN connection to the address; with none that covers it, stop and tell the person, who connects the agent at the address's page) say the rest. |
42
+ | The rules | The workspace's, the console's own until an administrator writes the organization's, and this project's own when it has them: which skills to load first, where the work lives, the pages, what may be decided alone, how to report ([ADR-0023](/docs/adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)). `console take` prints them with the task, so they are read once, there; `console rules` reads them without taking, as when a task is still to be chosen. They hold over this skill's defaults where they differ. |
43
43
 
44
44
  ## Workflow
45
45
 
@@ -47,7 +47,7 @@ Each phase ends with something on the board. Only phase 4 waits for a person.
47
47
 
48
48
  ### Phase 1: Read
49
49
 
50
- `console task <number>` shows the task in full, with its plan, the decisions about it and the runs on it. A run open on it means another agent was at it, and may still be: the console cannot tell ([ADR-0020](/docs/adr/0020-the-console-does-not-claim-an-agent-is-at-work-a-run-says-when-it-was-last-heard-from-and-a-new-run-takes-over.md)), so read its reports and when it was last heard from, and take the task only when the person said to, since taking it ends that run as taken over; otherwise say so and stop. A task that is past its due day is still the task; the first report says so, and what the day was for is kept in mind. Read what the body links to, with `console doc <path>` for the project's pages and `console skills` for the organization's skills, before anything is made.
50
+ Told which task, go to phase 2: `console take` prints the rules of the board with the task, and they are read there, once. Choosing one, or checking one before taking it, `console rules` says which tasks to take and what to load, and `console task <number>` shows a task in full, with its plan, the decisions about it and the runs on it, without taking it. A run open on it means another agent was at it, and may still be: the console cannot tell ([ADR-0020](/docs/adr/0020-the-console-does-not-claim-an-agent-is-at-work-a-run-says-when-it-was-last-heard-from-and-a-new-run-takes-over.md)), so read its reports and when it was last heard from, and take the task only when the person said to, since taking it ends that run as taken over; otherwise say so and stop. A task that is past its due day is still the task; the first report says so, and what the day was for is kept in mind. Read what the body links to, with `console doc <path>` for the project's pages and `console skills` for the organization's skills, before anything is made.
51
51
 
52
52
  ### Phase 2: Take
53
53
 
@@ -75,7 +75,7 @@ After the last report, `console finish --summary "<what was done, and what is le
75
75
 
76
76
  ## Setting up, when told to
77
77
 
78
- A task or a person may ask for the project itself rather than work in it: a project made or changed (`console project new <key> "<name>"`, `console project edit <key>`), its mark (`console project icon <key> <file>`), its members (`console member add <login>`, `console member role`, `console member remove`), the workspace's categories (`console category new <key> "<name>"`, `console category edit`, `console category remove`), what a person is (`console person role <login> <admin|member>`), and its goals (`console goal new`). The agent does these as its person may, an owner of the project or an administrator of the workspace ([ADR-0021](/docs/adr/0021-a-token-configures-as-its-person-does.md)); the feed names the agent beside the person on each. What the person may not, the console refuses (`auth.forbidden`): that step goes back to the person in the report, never worked around. `console people` and `console members` say who is who, by login.
78
+ A task or a person may ask for the project itself rather than work in it: a project made or changed (`console project new <key> "<name>"`, `console project edit <key>`), its mark (`console project icon <key> <file>`), its members (`console member add <login>`, `console member role`, `console member remove`), the workspace's categories (`console category new <key> "<name>"`, `console category edit`, `console category remove`), what a person is (`console person role <login> <admin|member>`), its goals (`console goal new`), and its rules (`console rules write --file <path>`, from [the example](references/project-rules.md); the workspace's with `--workspace`, for an administrator). The agent does these as its person may, an owner of the project or an administrator of the workspace ([ADR-0021](/docs/adr/0021-a-token-configures-as-its-person-does.md)); the feed names the agent beside the person on each. What the person may not, the console refuses (`auth.forbidden`): that step goes back to the person in the report, never worked around. `console people` and `console members` say who is who, by login.
79
79
 
80
80
  ## Hard rules
81
81
 
@@ -83,6 +83,7 @@ A task or a person may ask for the project itself rather than work in it: a proj
83
83
  - One run at a time: a command on a run acts on the one open run of this token in the project; working two tasks at once, say which with `--run <id>`.
84
84
  - The board's words are the vocabulary's own: states `idea`, `ready`, `in_progress`, `in_review`, `done` and `dropped`; priorities `low`, `normal`, `high` and `urgent`; a day is `2026-10-24`. Taking a task moves it, finishing moves it; it is not moved by hand around a run. When a task is started and when it is done, the board writes down itself: never typed.
85
85
  - The plan is the person's: a task's days, its category and its goal are changed (`console task edit`) only when the task says so or a person asks, and a goal is set or moved (`console goal new`, `console goal edit`) only when the person is an owner and said to.
86
+ - The rules are the people's: `console rules write` only when a person asked for exactly that, and never to loosen what they ask of agents.
86
87
  - Exit codes: `0` done; `1` refused or unreachable, the reason on standard error as a code and words, which `console help <command>` names; `2` not understood; `3` a decision still waits.
87
88
  - Everything sent is held to limits the console states (`console help <command>`); a refusal `request.invalid` names the field.
88
89
 
@@ -0,0 +1,36 @@
1
+ # An example of a project's rules
2
+
3
+ What an owner writes on a project's Settings page, or an agent writes with `console rules write --file <path>` when a person asked for exactly that: what the project adds to the workspace's rules, for the agents at work in it ([ADR-0023](/docs/adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)). An invented organization, Acme, and its web app. Short and true; what is long goes on a page the rules link to, and nothing secret goes in, since every agent reads them.
4
+
5
+ ~~~markdown
6
+ # Rules of this project
7
+
8
+ Adds to the workspace's rules, for the agents at work here.
9
+
10
+ ## Where the work lives
11
+
12
+ - The repository acme/web at the organization's git host: the web app. Its AGENTS.md holds inside it; `pnpm check` before every hand-in; a pull request, never a push to main.
13
+ - The design file: read only. A change to a design is a decision on the board.
14
+
15
+ ## Skills to load first
16
+
17
+ As `console skills` lists them, by the path of each. No connection that covers the address: stop and tell the person.
18
+
19
+ - `engineering/skills/working-in-web/SKILL.md`, for any task in the repository.
20
+ - `marketing/skills/release-notes/SKILL.md`, for a task in the category marketing.
21
+
22
+ ## The pages
23
+
24
+ - `guides/`: how a thing is set up or done. `guides/local-setup` first, every time.
25
+ - `notes/`: what was found; one page per topic, the date in the body, never in the path.
26
+ - `specs/`: what is being built, written by people. Agents read them and ask; never edit.
27
+
28
+ ## Decide alone, or ask
29
+
30
+ - Alone: anything inside the task and the repository's agreement; which tests to add.
31
+ - Ask: a new dependency; a change to the schema; anything a user would see differently than the spec says.
32
+
33
+ ## Reports
34
+
35
+ - In Korean, as the tasks are; at each milestone the task names, and when a check fails.
36
+ ~~~
@@ -0,0 +1,9 @@
1
+ // What an agent is called: what it said of itself when it connected, which the person approving
2
+ // kept or changed, and what a run was told with `--agent`. The command proposes "<agent> on
3
+ // <machine>", so the pages say the agent and keep the machine for a hover.
4
+
5
+ /** The agent's name before where it runs: "Claude Code" of "Claude Code on a laptop"; the whole name when it names no place. */
6
+ export function agentLabel(name: string): string {
7
+ const at = name.indexOf(" on ");
8
+ return at > 0 && at + 4 < name.length ? name.slice(0, at) : name;
9
+ }
package/src/api.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  // custom UI talks to any console with types, and so that the contract has one source. No React
4
4
  // here: the server and the command line import this entry point, and nothing of the pages.
5
5
 
6
+ export { agentLabel } from "./agent-name.js";
6
7
  export {
7
8
  ApiError,
8
9
  type ClientOptions,
@@ -51,6 +52,7 @@ export {
51
52
  MAX_LANGUAGE_TAG_LENGTH,
52
53
  MAX_LINK_LABEL_LENGTH,
53
54
  MAX_LINKS,
55
+ MAX_LOGIN_LENGTH,
54
56
  MAX_NOTE_LENGTH,
55
57
  MAX_OPTION_LABEL_LENGTH,
56
58
  MAX_OPTIONS,
@@ -61,6 +63,7 @@ export {
61
63
  MAX_PROJECT_SYMBOL_LENGTH,
62
64
  MAX_QUESTION_LENGTH,
63
65
  MAX_REPORTS_PER_RUN,
66
+ MAX_RULES_LENGTH,
64
67
  MAX_SEARCH_LENGTH,
65
68
  MAX_SECRET_LENGTH,
66
69
  MAX_SKILLS_ADDRESS_LENGTH,
@@ -84,17 +87,31 @@ export {
84
87
  PROJECT_COLLECTIONS,
85
88
  type ProjectCollection,
86
89
  personTokensPath,
90
+ personWorkPath,
87
91
  projectIconPath,
88
92
  projectPath,
89
93
  REST_ROUTES,
90
94
  RETURN_TO_PARAM,
91
95
  restPath,
96
+ rulesPath,
92
97
  SIGN_IN_FAILURES,
93
98
  SIGN_IN_PARAM,
94
99
  type SignInFailure,
95
100
  signInPath,
96
101
  } from "./routes.js";
97
102
  export {
103
+ fillRules,
104
+ isReferenceRules,
105
+ languageNameOf,
106
+ PROJECT_RULES_TEMPLATE,
107
+ REFERENCE_RULES,
108
+ RULES_LANGUAGE_PLACEHOLDER,
109
+ RULES_PATH,
110
+ RULES_TITLE,
111
+ } from "./rules.js";
112
+ export {
113
+ hostOfLogin,
114
+ isLoginAt,
98
115
  type RestAnswerInput,
99
116
  type RestArtifact,
100
117
  type RestArtifactInput,
@@ -129,23 +146,30 @@ export {
129
146
  type RestGoalInput,
130
147
  type RestGoalPatch,
131
148
  type RestGoals,
149
+ type RestListing,
150
+ type RestListingInput,
132
151
  type RestMe,
133
152
  type RestMember,
134
153
  type RestMemberInput,
135
154
  type RestMemberPatch,
136
155
  type RestMembers,
137
156
  type RestMePatch,
157
+ type RestOrganization,
138
158
  type RestPeople,
139
159
  type RestPerson,
140
160
  type RestPersonPatch,
161
+ type RestPersonWork,
141
162
  type RestProject,
142
163
  type RestProjectIcon,
143
164
  type RestProjectInput,
144
165
  type RestProjectPatch,
166
+ type RestProjectRules,
145
167
  type RestProjects,
146
168
  type RestProvider,
147
169
  type RestReport,
148
170
  type RestReportInput,
171
+ type RestRules,
172
+ type RestRulesInput,
149
173
  type RestRun,
150
174
  type RestRunEndInput,
151
175
  type RestRunInput,
@@ -200,23 +224,30 @@ export {
200
224
  restGoalPatchSchema,
201
225
  restGoalSchema,
202
226
  restGoalsSchema,
227
+ restListingInputSchema,
228
+ restListingSchema,
203
229
  restMemberInputSchema,
204
230
  restMemberPatchSchema,
205
231
  restMemberSchema,
206
232
  restMembersSchema,
207
233
  restMePatchSchema,
208
234
  restMeSchema,
235
+ restOrganizationSchema,
209
236
  restPeopleSchema,
210
237
  restPersonPatchSchema,
211
238
  restPersonSchema,
239
+ restPersonWorkSchema,
212
240
  restProjectIconSchema,
213
241
  restProjectInputSchema,
214
242
  restProjectPatchSchema,
243
+ restProjectRulesSchema,
215
244
  restProjectSchema,
216
245
  restProjectsSchema,
217
246
  restProviderSchema,
218
247
  restReportInputSchema,
219
248
  restReportSchema,
249
+ restRulesInputSchema,
250
+ restRulesSchema,
220
251
  restRunEndInputSchema,
221
252
  restRunInputSchema,
222
253
  restRunSchema,
@@ -253,9 +284,13 @@ export {
253
284
  isProviderKey,
254
285
  LINK_SOURCES,
255
286
  type LinkSource,
287
+ MEMBERSHIP_SOURCES,
288
+ type MembershipSource,
256
289
  OPEN_TASK_STATES,
257
290
  PERSON_ROLES,
291
+ PERSON_STATUSES,
258
292
  type PersonRole,
293
+ type PersonStatus,
259
294
  PROJECT_ICON_TYPES,
260
295
  PROJECT_ROLES,
261
296
  PROJECT_VISIBILITIES,
@@ -264,8 +299,10 @@ export {
264
299
  type ProjectRole,
265
300
  type ProjectVisibility,
266
301
  type ProviderKey,
302
+ RULES_SOURCES,
267
303
  RUN_ENDINGS,
268
304
  RUN_STATUSES,
305
+ type RulesSource,
269
306
  type RunEnding,
270
307
  type RunStatus,
271
308
  SKILLS_STATUSES,