@skillcdn/console 0.1.11 → 0.1.13

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 (71) hide show
  1. package/README.md +8 -5
  2. package/dist/cli/cli.d.ts.map +1 -1
  3. package/dist/cli/cli.js +260 -6
  4. package/dist/cli/cli.js.map +1 -1
  5. package/dist/cli/format.d.ts +7 -1
  6. package/dist/cli/format.d.ts.map +1 -1
  7. package/dist/cli/format.js +22 -0
  8. package/dist/cli/format.js.map +1 -1
  9. package/dist/cli/help.d.ts.map +1 -1
  10. package/dist/cli/help.js +69 -2
  11. package/dist/cli/help.js.map +1 -1
  12. package/dist/components/board.d.ts.map +1 -1
  13. package/dist/components/board.js +2 -2
  14. package/dist/components/board.js.map +1 -1
  15. package/dist/components/calendar.js +2 -2
  16. package/dist/components/calendar.js.map +1 -1
  17. package/dist/components/people.js +2 -2
  18. package/dist/components/people.js.map +1 -1
  19. package/dist/components/projects.d.ts.map +1 -1
  20. package/dist/components/projects.js +3 -3
  21. package/dist/components/projects.js.map +1 -1
  22. package/dist/components/runs.js +2 -2
  23. package/dist/components/runs.js.map +1 -1
  24. package/dist/components/shell.js +2 -2
  25. package/dist/components/shell.js.map +1 -1
  26. package/dist/components/task-form.js +2 -2
  27. package/dist/components/task-form.js.map +1 -1
  28. package/dist/components/ui.d.ts +7 -2
  29. package/dist/components/ui.d.ts.map +1 -1
  30. package/dist/components/ui.js +9 -4
  31. package/dist/components/ui.js.map +1 -1
  32. package/dist/console.d.ts +41 -6
  33. package/dist/console.d.ts.map +1 -1
  34. package/dist/console.js +61 -50
  35. package/dist/console.js.map +1 -1
  36. package/dist/i18n/en.d.ts +5 -5
  37. package/dist/i18n/en.d.ts.map +1 -1
  38. package/dist/i18n/en.js +8 -8
  39. package/dist/i18n/en.js.map +1 -1
  40. package/dist/i18n/ko.d.ts.map +1 -1
  41. package/dist/i18n/ko.js +8 -8
  42. package/dist/i18n/ko.js.map +1 -1
  43. package/dist/index.d.ts +3 -3
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -3
  46. package/dist/index.js.map +1 -1
  47. package/dist/router.d.ts +15 -0
  48. package/dist/router.d.ts.map +1 -1
  49. package/dist/router.js +17 -0
  50. package/dist/router.js.map +1 -1
  51. package/docs/specs/cli.md +15 -2
  52. package/docs/specs/rest.md +13 -13
  53. package/package.json +1 -1
  54. package/skills/building-a-console/SKILL.md +4 -4
  55. package/skills/working-the-board/SKILL.md +5 -1
  56. package/src/cli/cli.ts +333 -5
  57. package/src/cli/format.ts +27 -0
  58. package/src/cli/help.ts +86 -1
  59. package/src/components/board.tsx +11 -2
  60. package/src/components/calendar.tsx +2 -2
  61. package/src/components/people.tsx +5 -5
  62. package/src/components/projects.tsx +5 -3
  63. package/src/components/runs.tsx +2 -2
  64. package/src/components/shell.tsx +3 -3
  65. package/src/components/task-form.tsx +2 -2
  66. package/src/components/ui.tsx +14 -5
  67. package/src/console.tsx +115 -54
  68. package/src/i18n/en.ts +9 -8
  69. package/src/i18n/ko.ts +9 -8
  70. package/src/index.ts +5 -0
  71. package/src/router.ts +26 -0
package/docs/specs/cli.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  ## Signing in
7
7
 
8
- A person installs the package where the agent runs, or has the agent install it, and the command connects once ([ADR-0011](../adr/0011-an-agent-connects-with-a-short-code-a-person-approves-and-the-token-is-never-shown.md)): `console login --url <origin>` asks the console to connect, prints the address of the console's own page and a code of eight characters, and waits; the person opens the address signed in, checks that the page shows the same code, names the agent and approves; and the command receives a token of its own, which it never prints. An agent that can run commands does this itself and relays the address and the code to its person; `--agent <name>` says what it calls itself, shown to the person with the machine's name. A token made by hand on the Agents page is read from standard input with `--token-stdin` instead, for a script or a job, and checked against the console (`GET /api/v1/me` must know the person). Either way the command keeps the token with the address in `$XDG_CONFIG_HOME/skillcdn-console/credentials.json` (`~/.config/skillcdn-console/credentials.json` when `XDG_CONFIG_HOME` is unset), readable by the person alone where the system can say so. `CONSOLE_URL` and `CONSOLE_TOKEN` in the environment win over the file, for a hook or a job; `--url <origin>` names another console for one command. `logout` forgets the file; the token itself is removed on the Agents page, by its person or by an administrator. A token is never taken on the command line, never typed, and never printed.
8
+ A person installs the package where the agent runs, or has the agent install it, and the command connects once ([ADR-0011](../adr/0011-an-agent-connects-with-a-short-code-a-person-approves-and-the-token-is-never-shown.md)): `console login --url <origin>` asks the console to connect, prints the address of the console's own page and a code of eight characters, and waits, up to the thirty minutes the code is good for; the person opens the address signed in, checks that the page shows the same code, names the agent and approves; and the command receives a token of its own, which it never prints. An agent that can run commands does this itself and relays the address and the code to its person; `--agent <name>` says what it calls itself, shown to the person with the machine's name. A token made by hand on the Agents page is read from standard input with `--token-stdin` instead, for a script or a job, and checked against the console (`GET /api/v1/me` must know the person). Either way the command keeps the token with the address in `$XDG_CONFIG_HOME/skillcdn-console/credentials.json` (`~/.config/skillcdn-console/credentials.json` when `XDG_CONFIG_HOME` is unset), readable by the person alone where the system can say so. `CONSOLE_URL` and `CONSOLE_TOKEN` in the environment win over the file, for a hook or a job; `--url <origin>` names another console for one command. `logout` forgets the file; the token itself is removed on the Agents page, by its person or by an administrator. A token is never taken on the command line, never typed, and never printed.
9
9
 
10
10
  From then on the agent is that person on the board ([ADR-0004](../adr/0004-people-and-agents-reach-the-board-only-through-the-api-with-a-credential-of-their-own.md)): what it does is attributed to the person and shown as done by the agent, called what the person called the token unless `take --agent` says otherwise.
11
11
 
@@ -32,6 +32,15 @@ The board is a project's ([ADR-0008](../adr/0008-a-workspace-holds-projects-and-
32
32
  | `goal new <title> [--body <markdown>\|--file <path>] [--state <state>] [--due <day>]` | `POST .../goals` | the title and the id; for an owner of the project |
33
33
  | `goal edit <id> [--title <title>] [--body ...] [--state <state>] [--due <day\|none>]` | `PATCH .../goals/<id>` | the goal in full, as it is now |
34
34
  | `categories` | `GET /api/v1/categories` | one line per category: key, name, colour |
35
+ | `people` | `GET /api/v1/people` | one line per person: login, name, role in the workspace. Needs no project |
36
+ | `person role <login> <admin\|member>` | `GET /api/v1/people` for the id, then `PATCH /api/v1/people/<id>` | the person as they are now; for an administrator |
37
+ | `project <key>` | `GET /api/v1/projects/<key>` | the project in full: what it is, its mark, its skills address, what the person is in it |
38
+ | `project new <key> <name> [--description <markdown>\|--file <path>] [--visibility workspace\|private] [--skills <address>\|none] [--color <name>] [--symbol <text>]` | `POST /api/v1/projects` | the key and the name; the person is its owner |
39
+ | `project edit <key> [--name <name>] [the same flags; `none` clears]` | `PATCH /api/v1/projects/<key>` | the project in full, as it is now; for an owner |
40
+ | `project icon <key> <file>`, `project icon <key> --remove` | `POST .../icon` as a form, or `DELETE .../icon` | the same |
41
+ | `members` | `GET .../members` | one line per member: login, role, since when |
42
+ | `member add <login> [--role owner\|member]`, `member role <login> <owner\|member>`, `member remove <login>` | `GET /api/v1/people` for the id, then `POST .../members`, `PATCH .../members/<id>`, `DELETE .../members/<id>` | the member as they are now, or that they are no longer listed; for an owner |
43
+ | `category new <key> <name> [--color <name>]`, `category edit <key> [--name <name>] [--color <name>]`, `category remove <key>` | `POST /api/v1/categories`, `PATCH .../categories/<key>`, `DELETE .../categories/<key>` | the category as it is now, or that it is gone; for an administrator |
35
44
  | `skills` | `GET .../skills` | the project's skills, or the organization's: each with its description and the URI an agent loads it by through its own SkillCDN connection; or why there are none to show |
36
45
  | `take <number\|id> [--agent <name>]` | `GET .../tasks/<ref>`, then `POST .../runs` | the run that began, the task in full, and what to do next; a run open on the task is taken 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)) |
37
46
  | `report <markdown>`, `report --file <path>`, `report -` | `POST .../runs/<id>/reports` | how many reports the run carries |
@@ -59,6 +68,10 @@ The board is a project's ([ADR-0008](../adr/0008-a-workspace-holds-projects-and-
59
68
 
60
69
  A 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)), by path (`guides/onboarding`): `console docs` lists a folder, `console doc` reads a page, `console write` writes one, the first version or the next, keeping the title when none is said, `console attach` adds a file from the machine, `console archive` and `console restore` put a page away and bring it back. A link in a body whose destination is a page's path refers to that page, and `console doc` says what refers to a page in return. An agent writes down what it learned where the next agent will read it, and refers to it from its reports and in what it asks.
61
70
 
71
+ ## Configuring, as the person
72
+
73
+ What an administrator or an owner does on the pages, their agent does with `people`, `person role`, `project`, `members`, `member` and `category` ([ADR-0021](../adr/0021-a-token-configures-as-its-person-does.md)): the console decides on every request with the same roles, so a member's agent is refused what a member is (`auth.forbidden`), and the event names the agent beside the person. `console help` lists them under "Configuring, as the person", each with its limits and its refusals by code: `project.key_taken`, `project.invalid_address`, `project.invalid_icon`, `member.invalid_person`, `member.exists`, `member.not_found`, `category.key_taken`, `category.in_use`, `category.too_many`, `person.last_admin`. A person is named by login, as `--assignee` names one; `console people` lists the logins. The tokens themselves have no command: they are made and removed on the Agents page, signed in, so that a token which leaks cannot outlive its removal.
74
+
62
75
  ## The run a command means
63
76
 
64
77
  `report`, `hand-in`, `ask`, `finish` and `fail` act on a run. Named with `--run <id>`, that one; else the one open run begun with this token in the project (`GET .../runs?open=true&mine=true`). None open, or several: the command exits with `1` and says so, listing the open ones, so that an agent working two tasks at once says which.
@@ -86,7 +99,7 @@ Plain text on standard output: one line per thing in a list, a few lines for one
86
99
 
87
100
  ## What an agent is told
88
101
 
89
- `console help` says what the board is, that the agent acts as the person whose token it holds and that everything it sends is shown to people as text, which project the commands work in and how it is named, what each command does (take a task, report at the milestones of the work, hand in what was made, ask when a person must decide, finish when done, write and read the project's pages), and the refusals any command may meet. `console help <command>` adds what the command takes, the limits the console holds it to (how long a report, a summary, a question or an option may be; how many options, reports and links) and the refusals it may meet, by code, so that an agent learns them before it runs into them. The skill `working-the-board` ([skills/working-the-board/SKILL.md](../../skills/working-the-board/SKILL.md), [ADR-0015](../adr/0015-the-consoles-skills-live-in-this-repository-in-the-skillcdn-format-and-the-package-carries-them.md)) says how the work goes: reading, taking, reporting at the milestones, asking and waiting, handing in, writing down, finishing. An organization's own skill for its console adds the rest: which tasks to take, what to report, when to ask.
102
+ `console help` says what the board is, that the agent acts as the person whose token it holds and that everything it sends is shown to people as text, which project the commands work in and how it is named, what each command does (take a task, report at the milestones of the work, hand in what was made, ask when a person must decide, finish when done, write and read the project's pages, set up a project, its members and the categories when told to), and the refusals any command may meet. `console help <command>` adds what the command takes, the limits the console holds it to (how long a report, a summary, a question or an option may be; how many options, reports and links) and the refusals it may meet, by code, so that an agent learns them before it runs into them. The skill `working-the-board` ([skills/working-the-board/SKILL.md](../../skills/working-the-board/SKILL.md), [ADR-0015](../adr/0015-the-consoles-skills-live-in-this-repository-in-the-skillcdn-format-and-the-package-carries-them.md)) says how the work goes: reading, taking, reporting at the milestones, asking and waiting, handing in, writing down, finishing. An organization's own skill for its console adds the rest: which tasks to take, what to report, when to ask.
90
103
 
91
104
  ## Running an agent on a task
92
105
 
@@ -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
- - Configuring is a person's own doing, signed in on the console's own pages, never with a token: the tokens themselves, roles, projects and their members.
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.
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.
@@ -37,7 +37,7 @@ The API is the board as its members see it: the people, the projects, and in eac
37
37
  | 401 | `auth.required` | Nobody is signed in, or the session has ended, or the token is nothing. The cookie is taken away when the operator no longer lists the login. |
38
38
  | 403 | `auth.forbidden_origin` | A request that changes something on a session did not come from the console's own pages. |
39
39
  | 403 | `auth.forbidden` | A member asked for what only an administrator, or only an owner of the project, may do. |
40
- | 403 | `auth.session_required` | A token asked for what only a person signed in may do: the tokens themselves, and configuring. |
40
+ | 403 | `auth.session_required` | A token asked for what only a person signed in may do: the tokens themselves, and the approval of an agent's connection, which makes one. |
41
41
  | 403 | `run.not_yours` | The run is another person's. |
42
42
  | 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
43
  | 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. |
@@ -69,11 +69,11 @@ The API is the board as its members see it: the people, the projects, and in eac
69
69
 
70
70
  ### `GET /api/v1/people`
71
71
 
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.
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.
73
73
 
74
74
  ### `PATCH /api/v1/people/<id>`
75
75
 
76
- Takes `role` and answers the person. For an administrator signed in on the console's own pages, never with a token: an agent works as its person does, and configuring is a person's own doing. 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.
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.
77
77
 
78
78
  ### `GET /api/v1/projects`
79
79
 
@@ -81,7 +81,7 @@ Takes `role` and answers the person. For an administrator signed in on the conso
81
81
 
82
82
  ### `POST /api/v1/projects`
83
83
 
84
- Takes `key` and `name`, and optionally `description`, `visibility` (default `private`), `skillsAddress` (checked as the standard spells one, kept canonical; `project.invalid_address`), `color` and `symbol`. For whoever is signed in on the console's own pages, never with a token; they become the project's owner. Answers `201` with the project and writes a `project.created` event in it, with `key` and `name`. A key taken is `project.key_taken`.
84
+ Takes `key` and `name`, and optionally `description`, `visibility` (default `private`), `skillsAddress` (checked as the standard spells one, kept canonical; `project.invalid_address`), `color` and `symbol`. For whoever is signed in, or their agent with their token; they become the project's owner. Answers `201` with the project and writes a `project.created` event in it, with `key` and `name`. A key taken is `project.key_taken`.
85
85
 
86
86
  ### `GET /api/v1/events?after=&limit=`
87
87
 
@@ -89,7 +89,7 @@ The workspace's own events, the ones about no project: who joined (`person.joine
89
89
 
90
90
  ### `PATCH /api/v1/me`
91
91
 
92
- Keeps the person's own choice of language for the pages ([ADR-0012](../adr/0012-the-pages-speak-the-persons-language-from-packs-that-ship-with-the-package.md)): `{ "language": "ko" }`, a language tag as a browser sends one, or `null` to choose none and let the browser's languages decide; answers what `GET` answers. A person's own doing, from the console's own pages: never with a token.
92
+ Keeps the person's own choice of language for the pages ([ADR-0012](../adr/0012-the-pages-speak-the-persons-language-from-packs-that-ship-with-the-package.md)): `{ "language": "ko" }`, a language tag as a browser sends one, or `null` to choose none and let the browser's languages decide; answers what `GET` answers. From the console's own pages, or with a token: a console of a person's own keeps the choice on the person too.
93
93
 
94
94
  ### `GET /api/v1/categories`
95
95
 
@@ -97,7 +97,7 @@ Keeps the person's own choice of language for the pages ([ADR-0012](../adr/0012-
97
97
 
98
98
  ### `POST /api/v1/categories`, `PATCH /api/v1/categories/<key>` and `DELETE /api/v1/categories/<key>`
99
99
 
100
- Kept by an administrator signed in on the console's own pages, never with a token, as the rest of configuring is. `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.
100
+ 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
101
 
102
102
  ### `GET /api/v1/work`
103
103
 
@@ -119,7 +119,7 @@ An administrator's sight of everyone's agents ([ADR-0011](../adr/0011-an-agent-c
119
119
 
120
120
  `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)).
121
121
 
122
- `POST /api/v1/connect` is nobody's: the command sends `{ "agent" }` (what the agent calls itself and where it runs, a line up to `MAX_TOKEN_NAME_LENGTH`) and is answered `201` with `{ "code", "url", "secret", "expiresAt", "interval" }`: a code of eight characters in two groups (`ABCD-EFGH`, from an alphabet without look-alikes) for a person to approve, the console's own page for it, a secret (`cns_c_...`) the command claims with and shows nowhere, when the request expires (ten minutes after it began), and how many seconds the command waits between claims. A deployment holds a bounded number of requests at once (`connect.too_many`).
122
+ `POST /api/v1/connect` is nobody's: the command sends `{ "agent" }` (what the agent calls itself and where it runs, a line up to `MAX_TOKEN_NAME_LENGTH`) and is answered `201` with `{ "code", "url", "secret", "expiresAt", "interval" }`: a code of eight characters in two groups (`ABCD-EFGH`, from an alphabet without look-alikes) for a person to approve, the console's own page for it, a secret (`cns_c_...`) the command claims with and shows nowhere, when the request expires (thirty minutes after it began), and how many seconds the command waits between claims. A deployment holds a bounded number of requests at once (`connect.too_many`).
123
123
 
124
124
  `GET /api/v1/connect/<code>`, for a person signed in, answers what asks: `{ "code", "agent", "createdAt", "expiresAt", "approved" }`. A code is read as a person types it: any case, with or without the hyphen. `POST .../approve`, from the console's own pages, takes what `POST /api/v1/tokens` takes (`name`, `expiresInDays`) and answers the request, approved; `POST .../deny` takes the request away and answers `204`.
125
125
 
@@ -131,19 +131,19 @@ Everything below is under `/api/v1/projects/<key>`, for whoever may see the proj
131
131
 
132
132
  ### `GET /api/v1/projects/<key>` and `PATCH /api/v1/projects/<key>`
133
133
 
134
- The project, as the asker sees it. A patch, for an owner signed in, takes any of `name`, `description`, `visibility`, `skillsAddress` (`null` for the organization's), `color` and `symbol` (`null` for none), and writes a `project.updated` event naming the `fields`; what is already so writes nothing. The key does not change.
134
+ The project, as the asker sees it. A patch, for an owner, signed in or with a token, takes any of `name`, `description`, `visibility`, `skillsAddress` (`null` for the organization's), `color` and `symbol` (`null` for none), and writes a `project.updated` event naming the `fields`; what is already so writes nothing. The key does not change.
135
135
 
136
136
  ### `POST /api/v1/projects/<key>/icon`, `DELETE .../icon` and `GET .../icon`
137
137
 
138
- The project's own image for its mark, in place of the symbol on the colour. `POST`, for an owner signed in on the console's own pages, takes a form with a part called `file`: a PNG, a JPEG, a GIF or a WebP of at most `MAX_PROJECT_ICON_BYTES`, known by its first bytes and never by what the form says of it (`project.invalid_icon`; `request.too_large`). The bytes are kept by their hash, the project is answered with its `icon`, and the board hears `project.updated` with `fields: ["icon"]`; the same image again writes nothing. `DELETE` takes the image away and answers the project. `GET`, for whoever may see the project, answers the bytes with their type, the hash as `ETag` and `Cache-Control: private, max-age=86400`, or `304` to a matching `If-None-Match`; a project without an image is `project.no_icon`. The pages read it at `projectIconPath(key, icon)`, which carries the hash as a version.
138
+ The project's own image for its mark, in place of the symbol on the colour. `POST`, for an owner, takes a form with a part called `file`: a PNG, a JPEG, a GIF or a WebP of at most `MAX_PROJECT_ICON_BYTES`, known by its first bytes and never by what the form says of it (`project.invalid_icon`; `request.too_large`). The bytes are kept by their hash, the project is answered with its `icon`, and the board hears `project.updated` with `fields: ["icon"]`; the same image again writes nothing. `DELETE` takes the image away and answers the project. `GET`, for whoever may see the project, answers the bytes with their type, the hash as `ETag` and `Cache-Control: private, max-age=86400`, or `304` to a matching `If-None-Match`; a project without an image is `project.no_icon`. The pages read it at `projectIconPath(key, icon)`, which carries the hash as a version.
139
139
 
140
140
  ### `GET /api/v1/projects/<key>/members` and `POST /api/v1/projects/<key>/members`
141
141
 
142
- `{ "items": [member, ...] }`: those listed in the project, by login, each a `person`, their `role` in it (`owner`, `member`) and `addedAt`. A project open to the workspace has everyone of it as a member besides; an administrator is an owner of every project, listed or not. `POST`, for an owner signed in, takes `personId` (a person of the workspace; `member.invalid_person`) and optionally `role` (default `member`), answers `201` with the member and writes `project.member_added` with `login` and `role`. A person listed already is `member.exists`.
142
+ `{ "items": [member, ...] }`: those listed in the project, by login, each a `person`, their `role` in it (`owner`, `member`) and `addedAt`. A project open to the workspace has everyone of it as a member besides; an administrator is an owner of every project, listed or not. `POST`, for an owner, takes `personId` (a person of the workspace; `member.invalid_person`) and optionally `role` (default `member`), answers `201` with the member and writes `project.member_added` with `login` and `role`. A person listed already is `member.exists`.
143
143
 
144
144
  ### `PATCH /api/v1/projects/<key>/members/<person id>` and `DELETE .../members/<person id>`
145
145
 
146
- For an owner signed in. The patch takes `role` and writes `project.member_changed`; the removal answers `204` and writes `project.member_removed`. A person not listed is `member.not_found`. A project may be left without an owner listed; the administrators own it then.
146
+ For an owner, signed in or with a token. The patch takes `role` and writes `project.member_changed`; the removal answers `204` and writes `project.member_removed`. A person not listed is `member.not_found`. A project may be left without an owner listed; the administrators own it then.
147
147
 
148
148
  ### `GET /api/v1/projects/<key>/tasks?state=&open=&category=&goal=&assignee=&dueBy=&limit=&offset=`
149
149
 
@@ -203,7 +203,7 @@ The bytes are read back at `/api/v1/projects/<key>/files/<artifact id>` by whoev
203
203
 
204
204
  ### `POST .../runs/<id>/end`
205
205
 
206
- Takes `status` (`finished`, `failed` or `abandoned`) and optionally a `summary` (Markdown, `MAX_SUMMARY_LENGTH`: what was done and what is left), ends the run (`run.ended`), and answers it. A finished run puts a task that was `in_progress` up for review (`in_review`); the rest leave the task as it is. The run's person ends it, as `finished` or `failed` from their agent; `abandoned` is a person giving up on a run that will not come back: their own, or anyone's as an owner of the project signed in on the console's own pages, never with a token (`run.not_yours`). A run that is over is `run.over`.
206
+ Takes `status` (`finished`, `failed` or `abandoned`) and optionally a `summary` (Markdown, `MAX_SUMMARY_LENGTH`: what was done and what is left), ends the run (`run.ended`), and answers it. A finished run puts a task that was `in_progress` up for review (`in_review`); the rest leave the task as it is. The run's person ends it, as `finished` or `failed` from their agent; `abandoned` is a person giving up on a run that will not come back: their own, or anyone's as an owner of the project, signed in or through their agent (`run.not_yours` otherwise). A run that is over is `run.over`.
207
207
 
208
208
  ### `GET /api/v1/projects/<key>/skills`
209
209
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillcdn/console",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
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",
@@ -5,7 +5,7 @@ license: MIT
5
5
  compatibility: A shell with Node.js 24 or newer and npm or pnpm, and an agent that reads and writes files. For looking at the pages against a board, the console command signed in by a person. A browser the agent can drive is optional. No key of the agent's own is needed, and it never sees a token.
6
6
  metadata:
7
7
  author: skillcdn
8
- version: "1.2"
8
+ version: "1.3"
9
9
  skillcdn:
10
10
  translations:
11
11
  ko:
@@ -66,15 +66,15 @@ Produces the **plan** and the first build. Install first, in the new folder, so
66
66
 
67
67
  ### Phase 2: Configure before replacing
68
68
 
69
- Produces the **configuration**. `createConsole(config)` takes `title`; `brand`, the addresses of a symbol and a wordmark; `languages`, the packs the pages speak, where a language of one's own is `src/i18n/en.ts` copied whole and translated; `components`, the pieces to replace, with the props `ConsoleComponents` names; `baseUrl`, the API's origin, the page's own when left out; and `client`, for tests. A console with marks of its own imports their files in `main.tsx`, so that the build takes them as assets, and passes their addresses through `brand`; `build: { assetsInlineLimit: 0 }` in `vite.config.ts` keeps every picture and font a file, since the policy allows a small picture inlined as a `data:` address but no `data:` font, and the default console only happens to have none small enough; sets `index.html`'s `<title>`, its `lang` and its icons, the mark as `favicon.svg` linked directly, with an `.ico` and a touch icon when the person has them (the default console links three from its brand package through a small build plugin); and loads the faces its languages need. Most wants are configuration or the styles: re-skinning starts and mostly ends with the tokens of `console.css` (the colours, the glass, the field), overridden by a stylesheet of the console's own loaded after the package's, with the mapping of the plan. Replace a component only when configuration cannot do it: start from its source under `src/components/`, keep its props, and keep or add `sc-` classes. With the look in place, show the pages and stop for the look checkpoint.
69
+ Produces the **configuration**. `createConsole(config)` takes `title`; `brand`, the addresses of a symbol and a wordmark; `languages`, the packs the pages speak, where a language of one's own is `src/i18n/en.ts` copied whole and translated; `components`, the pieces to replace, with the props `ConsoleComponents` names; `pages`, tabs of the console's own, each a `CustomPage` with a key, a label by language, a level (the workspace's pages or every project's) and `render`, given the data, the client, the navigation and the words; `baseUrl`, the API's origin, the page's own when left out; and `client`, for tests. The look is the stylesheet's tokens, `--sc-*` on `:root`, set in a stylesheet of the console's own loaded after `console.css`, and the blocks are styled by their `sc-` classes; the package's README lists the tokens by group. A console with marks of its own imports their files in `main.tsx`, so that the build takes them as assets, and passes their addresses through `brand`; `build: { assetsInlineLimit: 0 }` in `vite.config.ts` keeps every picture and font a file, since the policy allows a small picture inlined as a `data:` address but no `data:` font, and the default console only happens to have none small enough; sets `index.html`'s `<title>`, its `lang` and its icons, the mark as `favicon.svg` linked directly, with an `.ico` and a touch icon when the person has them (the default console links three from its brand package through a small build plugin); and loads the faces its languages need. Most wants are configuration or the styles: re-skinning starts and mostly ends with the tokens of `console.css` (the colours, the glass, the field), overridden by a stylesheet of the console's own loaded after the package's, with the mapping of the plan. Replace a component only when configuration cannot do it: start from its source under `src/components/`, keep its props, and keep or add `sc-` classes. With the look in place, show the pages and stop for the look checkpoint.
70
70
 
71
71
  ### Phase 3: Compose pages of one's own
72
72
 
73
- Produces the **pages**. For a page the default console lacks: `useConsoleData(client, projectKey)` answers the workspace and the project the page is on, kept current by the project's stream, with the actions; the components take their data as props and nothing from the network; `matchRoute`, `PATHS`, `projectHref`, `taskHref`, `decisionHref` and `docHref` name the addresses; `Shell` is the header with the tabs and the person's menu. A composition of one's own is `src/console.tsx` with pages added or taken away. A request without a page of its own skips this phase.
73
+ Produces the **pages**. For a page the default console lacks: `useConsoleData(client, projectKey)` answers the workspace and the project the page is on, kept current by the project's stream, with the actions; the components take their data as props and nothing from the network; `matchRoute`, `PATHS`, `projectHref`, `taskHref`, `decisionHref` and `docHref` name the addresses; `Shell` is the header with the tabs and the person's menu. A page as a tab is `pages` in the configuration, its `render` composing the components over what it is given; a composition of one's own is `src/console.tsx` with pages added or taken away. A request without a page of its own skips this phase.
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 and configuring stay on the organization's console. 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, the settings) 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.
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.
78
78
 
79
79
  ### Phase 5: Check and show
80
80
 
@@ -5,7 +5,7 @@ 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.2"
8
+ version: "1.3"
9
9
  skillcdn:
10
10
  translations:
11
11
  ko:
@@ -73,6 +73,10 @@ What was learned and will be needed again (how a thing is set up, why a choice w
73
73
 
74
74
  After the last report, `console finish --summary "<what was done, and what is left>"`: the task goes up for review. `console fail --summary "<why, and what is left>"` when it could not be done. A run is never left open.
75
75
 
76
+ ## Setting up, when told to
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.
79
+
76
80
  ## Hard rules
77
81
 
78
82
  - Never look for, read, print or send a token. The rules of the repository say the rest.