@skillcdn/console 0.4.2 → 0.4.4
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.
- package/README.md +4 -4
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +3 -3
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +120 -33
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/format.d.ts +4 -2
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +38 -10
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +22 -15
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/plugin-check.d.ts +10 -1
- package/dist/cli/plugin-check.d.ts.map +1 -1
- package/dist/cli/plugin-check.js +45 -4
- package/dist/cli/plugin-check.js.map +1 -1
- package/dist/cli/plugin-cli.d.ts +1 -1
- package/dist/cli/plugin-cli.d.ts.map +1 -1
- package/dist/cli/plugin-cli.js +80 -5
- package/dist/cli/plugin-cli.js.map +1 -1
- package/dist/cli/plugin-init.d.ts +19 -0
- package/dist/cli/plugin-init.d.ts.map +1 -1
- package/dist/cli/plugin-init.js +141 -3
- package/dist/cli/plugin-init.js.map +1 -1
- package/dist/client.d.ts +7 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -5
- package/dist/client.js.map +1 -1
- package/dist/compat.js +1 -1
- package/dist/components/board.d.ts +8 -0
- package/dist/components/board.d.ts.map +1 -1
- package/dist/components/board.js +3 -3
- package/dist/components/board.js.map +1 -1
- package/dist/components/comments.d.ts.map +1 -1
- package/dist/components/comments.js +1 -1
- package/dist/components/comments.js.map +1 -1
- package/dist/components/decision-form.d.ts +8 -1
- package/dist/components/decision-form.d.ts.map +1 -1
- package/dist/components/decision-form.js +57 -7
- package/dist/components/decision-form.js.map +1 -1
- package/dist/components/decision-list.d.ts +9 -1
- package/dist/components/decision-list.d.ts.map +1 -1
- package/dist/components/decision-list.js +53 -7
- package/dist/components/decision-list.js.map +1 -1
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +7 -1
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/goals.d.ts.map +1 -1
- package/dist/components/goals.js +2 -2
- package/dist/components/goals.js.map +1 -1
- package/dist/components/home.d.ts +35 -0
- package/dist/components/home.d.ts.map +1 -0
- package/dist/components/home.js +326 -0
- package/dist/components/home.js.map +1 -0
- package/dist/components/my-decisions.d.ts +2 -0
- package/dist/components/my-decisions.d.ts.map +1 -1
- package/dist/components/my-decisions.js +2 -2
- package/dist/components/my-decisions.js.map +1 -1
- package/dist/components/pack-connect.d.ts.map +1 -1
- package/dist/components/pack-connect.js +5 -4
- package/dist/components/pack-connect.js.map +1 -1
- package/dist/components/people.d.ts +2 -0
- package/dist/components/people.d.ts.map +1 -1
- package/dist/components/people.js +15 -2
- package/dist/components/people.js.map +1 -1
- package/dist/components/plugin-frame.d.ts +3 -12
- package/dist/components/plugin-frame.d.ts.map +1 -1
- package/dist/components/plugin-frame.js +53 -20
- package/dist/components/plugin-frame.js.map +1 -1
- package/dist/components/plugin-settings.d.ts.map +1 -1
- package/dist/components/plugin-settings.js +151 -26
- package/dist/components/plugin-settings.js.map +1 -1
- package/dist/components/projects.d.ts +0 -8
- package/dist/components/projects.d.ts.map +1 -1
- package/dist/components/projects.js +1 -13
- package/dist/components/projects.js.map +1 -1
- package/dist/components/task-view.d.ts +2 -1
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js +2 -1
- package/dist/components/task-view.js.map +1 -1
- package/dist/components/ui.d.ts.map +1 -1
- package/dist/components/ui.js +5 -2
- package/dist/components/ui.js.map +1 -1
- package/dist/connect-page.d.ts.map +1 -1
- package/dist/connect-page.js +5 -6
- package/dist/connect-page.js.map +1 -1
- package/dist/console.css +764 -192
- package/dist/console.d.ts +10 -3
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +49 -28
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +6 -3
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +31 -7
- package/dist/data.js.map +1 -1
- package/dist/docs-page.d.ts.map +1 -1
- package/dist/docs-page.js +6 -5
- package/dist/docs-page.js.map +1 -1
- package/dist/home-tiles.d.ts +92 -0
- package/dist/home-tiles.d.ts.map +1 -0
- package/dist/home-tiles.js +294 -0
- package/dist/home-tiles.js.map +1 -0
- package/dist/i18n/en.d.ts +180 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +181 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/index.d.ts +4 -2
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +10 -11
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +176 -3
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +8 -0
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +8 -0
- package/dist/limits.js.map +1 -1
- package/dist/plugin/bridge.d.ts +44 -3
- package/dist/plugin/bridge.d.ts.map +1 -1
- package/dist/plugin/bridge.js +26 -0
- package/dist/plugin/bridge.js.map +1 -1
- package/dist/plugin/capabilities.d.ts +7 -1
- package/dist/plugin/capabilities.d.ts.map +1 -1
- package/dist/plugin/capabilities.js +14 -1
- package/dist/plugin/capabilities.js.map +1 -1
- package/dist/plugin/context.d.ts +24 -1
- package/dist/plugin/context.d.ts.map +1 -1
- package/dist/plugin/define.d.ts +1 -0
- package/dist/plugin/define.d.ts.map +1 -1
- package/dist/plugin/define.js +1 -1
- package/dist/plugin/define.js.map +1 -1
- package/dist/plugin/limits.d.ts +5 -2
- package/dist/plugin/limits.d.ts.map +1 -1
- package/dist/plugin/limits.js +5 -2
- package/dist/plugin/limits.js.map +1 -1
- package/dist/plugin/manifest.d.ts +83 -6
- package/dist/plugin/manifest.d.ts.map +1 -1
- package/dist/plugin/manifest.js +111 -7
- package/dist/plugin/manifest.js.map +1 -1
- package/dist/plugin/rest-schemas.d.ts +76 -0
- package/dist/plugin/rest-schemas.d.ts.map +1 -1
- package/dist/plugin/rest-schemas.js +23 -2
- package/dist/plugin/rest-schemas.js.map +1 -1
- package/dist/plugin/sandbox.d.ts +4 -3
- package/dist/plugin/sandbox.d.ts.map +1 -1
- package/dist/plugin/sandbox.js +33 -6
- package/dist/plugin/sandbox.js.map +1 -1
- package/dist/plugin/semver.d.ts +26 -0
- package/dist/plugin/semver.d.ts.map +1 -0
- package/dist/plugin/semver.js +76 -0
- package/dist/plugin/semver.js.map +1 -0
- package/dist/plugin/testing.d.ts.map +1 -1
- package/dist/plugin/testing.js +2 -1
- package/dist/plugin/testing.js.map +1 -1
- package/dist/plugin/web.d.ts +10 -1
- package/dist/plugin/web.d.ts.map +1 -1
- package/dist/plugin/web.js +34 -0
- package/dist/plugin/web.js.map +1 -1
- package/dist/plugin.d.ts +3 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +3 -2
- package/dist/plugin.js.map +1 -1
- package/dist/rules.d.ts +2 -2
- package/dist/rules.js +3 -3
- package/dist/schemas.d.ts +574 -11
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +154 -25
- package/dist/schemas.js.map +1 -1
- package/dist/use-action.d.ts +8 -2
- package/dist/use-action.d.ts.map +1 -1
- package/dist/use-action.js +13 -6
- package/dist/use-action.js.map +1 -1
- package/dist/vocabulary.d.ts +3 -1
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +3 -0
- package/dist/vocabulary.js.map +1 -1
- package/docs/specs/cli.md +4 -3
- package/docs/specs/plugins.md +49 -35
- package/docs/specs/rest.md +20 -18
- package/package.json +7 -7
- package/skills/building-a-plugin/SKILL.md +10 -9
- package/skills/planning-the-board/references/setting-up.md +2 -1
- package/skills/working-the-board/SKILL.md +3 -3
- package/src/api.ts +10 -0
- package/src/cli/cli.ts +162 -39
- package/src/cli/format.ts +54 -10
- package/src/cli/help.ts +23 -14
- package/src/cli/plugin-check.ts +68 -2
- package/src/cli/plugin-cli.ts +104 -6
- package/src/cli/plugin-init.ts +178 -3
- package/src/client.ts +36 -9
- package/src/compat.ts +1 -1
- package/src/components/board.tsx +3 -3
- package/src/components/comments.tsx +1 -0
- package/src/components/decision-form.tsx +166 -29
- package/src/components/decision-list.tsx +116 -15
- package/src/components/event-feed.tsx +7 -1
- package/src/components/goals.tsx +4 -1
- package/src/components/home.tsx +615 -0
- package/src/components/my-decisions.tsx +4 -1
- package/src/components/pack-connect.tsx +5 -4
- package/src/components/people.tsx +136 -54
- package/src/components/plugin-frame.tsx +62 -63
- package/src/components/plugin-settings.tsx +428 -87
- package/src/components/projects.tsx +0 -55
- package/src/components/task-view.tsx +9 -1
- package/src/components/ui.tsx +6 -2
- package/src/connect-page.tsx +5 -6
- package/src/console.tsx +98 -42
- package/src/data.ts +41 -11
- package/src/docs-page.tsx +6 -5
- package/src/home-tiles.ts +438 -0
- package/src/i18n/en.ts +185 -0
- package/src/i18n/index.ts +17 -14
- package/src/i18n/ko.ts +181 -3
- package/src/index.ts +7 -5
- package/src/limits.ts +8 -0
- package/src/plugin/bridge.ts +77 -1
- package/src/plugin/capabilities.ts +17 -1
- package/src/plugin/context.ts +24 -2
- package/src/plugin/define.ts +4 -1
- package/src/plugin/limits.ts +5 -2
- package/src/plugin/manifest.ts +154 -10
- package/src/plugin/rest-schemas.ts +27 -1
- package/src/plugin/sandbox.ts +36 -8
- package/src/plugin/semver.ts +89 -0
- package/src/plugin/testing.ts +2 -1
- package/src/plugin/web.ts +49 -0
- package/src/plugin.ts +18 -0
- package/src/rules.ts +3 -3
- package/src/schemas.ts +190 -28
- package/src/styles/console.css +764 -192
- package/src/use-action.ts +16 -7
- package/src/vocabulary.ts +4 -0
- package/template/plugin/console-plugin.json +3 -1
- package/template/plugin/package.json +3 -3
package/dist/use-action.js
CHANGED
|
@@ -4,12 +4,19 @@ import { en } from "./i18n/en.js";
|
|
|
4
4
|
import { useWords } from "./i18n/index.js";
|
|
5
5
|
// A change a page makes: run it, keep what went wrong for the page, and say while it is busy.
|
|
6
6
|
// Shared by the compositions, so that every page says the same thing the same way.
|
|
7
|
-
/**
|
|
8
|
-
export function
|
|
9
|
-
if (error instanceof ApiError) {
|
|
10
|
-
return
|
|
7
|
+
/** The pack's words for what the server answered, or nothing for a failure it has none for. */
|
|
8
|
+
export function wordsForFailure(error, pack) {
|
|
9
|
+
if (!(error instanceof ApiError) || !Object.hasOwn(pack.errors, error.code)) {
|
|
10
|
+
return undefined;
|
|
11
11
|
}
|
|
12
|
-
return
|
|
12
|
+
return pack.errors[error.code];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* What a failure says to a person: the code the server answered read in their language, the
|
|
16
|
+
* server's own message being English and for programs; `fallback` for the rest.
|
|
17
|
+
*/
|
|
18
|
+
export function errorWords(error, fallback = en.common.somethingWentWrong, pack = en) {
|
|
19
|
+
return wordsForFailure(error, pack) ?? fallback;
|
|
13
20
|
}
|
|
14
21
|
/** Runs a change, keeps what went wrong for the page, and says when it is busy. */
|
|
15
22
|
export function useAction() {
|
|
@@ -23,7 +30,7 @@ export function useAction() {
|
|
|
23
30
|
await work();
|
|
24
31
|
}
|
|
25
32
|
catch (failure) {
|
|
26
|
-
setError(errorWords(failure, words.common.somethingWentWrong));
|
|
33
|
+
setError(errorWords(failure, words.common.somethingWentWrong, words));
|
|
27
34
|
}
|
|
28
35
|
finally {
|
|
29
36
|
setBusy(false);
|
package/dist/use-action.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action.js","sourceRoot":"","sources":["../src/use-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"use-action.js","sourceRoot":"","sources":["../src/use-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,EAAE,EAAiB,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,8FAA8F;AAC9F,mFAAmF;AAEnF,+FAA+F;AAC/F,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,IAAc;IAC5D,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5E,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAQ,IAAI,CAAC,MAA2C,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,KAAc,EACd,QAAQ,GAAW,EAAE,CAAC,MAAM,CAAC,kBAAkB,EAC/C,IAAI,GAAa,EAAE;IAEnB,OAAO,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC;AAClD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,SAAS;IACvB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAqB,SAAS,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,KAAK,EAAE,IAA4B,EAAE,EAAE;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,OAAO,EAAE,CAAC;YACjB,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;QACxE,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC9B,CAAC"}
|
package/dist/vocabulary.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export type CategoryColor = ColorName;
|
|
|
27
27
|
export declare const PROJECT_ICON_TYPES: readonly ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
28
28
|
export type ProjectIconType = (typeof PROJECT_ICON_TYPES)[number];
|
|
29
29
|
/** The identity providers people may sign in through: the git host, and Google (Workspace). */
|
|
30
|
+
/** The languages the console's pages speak, and a plugin's words are given in. */
|
|
31
|
+
export declare const CONSOLE_LANGUAGES: readonly ["en", "ko"];
|
|
30
32
|
export declare const PROVIDER_KEYS: readonly ["gh", "google"];
|
|
31
33
|
export type ProviderKey = (typeof PROVIDER_KEYS)[number];
|
|
32
34
|
export declare function isProviderKey(value: string | null | undefined): value is ProviderKey;
|
|
@@ -99,7 +101,7 @@ export type RulesSource = (typeof RULES_SOURCES)[number];
|
|
|
99
101
|
* What can happen to the board. Every change of state is one of these, written down once with
|
|
100
102
|
* who did it: the live feed shows them as they happen, and the audit trail keeps them.
|
|
101
103
|
*/
|
|
102
|
-
export declare const EVENT_KINDS: readonly ["person.joined", "person.role_changed", "person.listed", "person.unlisted", "person.deactivated", "person.reactivated", "workspace.updated", "category.created", "category.updated", "category.removed", "project.created", "project.updated", "project.member_added", "project.member_changed", "project.member_removed", "goal.created", "goal.updated", "task.created", "task.updated", "task.moved", "task.commented", "task.archived", "task.restored", "decision.raised", "decision.answered", "decision.updated", "run.started", "run.reported", "run.handed_in", "run.taken_over", "run.ended", "document.written", "document.archived", "document.restored", "document.file_attached", "plugin.enabled", "plugin.disabled", "plugin.configured", "plugin.granted", "plugin.revoked", "plugin.upgraded", "plugin.command", "plugin.failed", "plugin.purged"];
|
|
104
|
+
export declare const EVENT_KINDS: readonly ["person.joined", "person.role_changed", "person.listed", "person.unlisted", "person.deactivated", "person.reactivated", "person.manager_changed", "workspace.updated", "category.created", "category.updated", "category.removed", "project.created", "project.updated", "project.member_added", "project.member_changed", "project.member_removed", "goal.created", "goal.updated", "task.created", "task.updated", "task.moved", "task.commented", "task.archived", "task.restored", "decision.raised", "decision.answered", "decision.updated", "run.started", "run.reported", "run.handed_in", "run.taken_over", "run.ended", "document.written", "document.archived", "document.restored", "document.file_attached", "plugin.enabled", "plugin.disabled", "plugin.configured", "plugin.granted", "plugin.revoked", "plugin.upgraded", "plugin.command", "plugin.failed", "plugin.purged"];
|
|
103
105
|
export type EventKind = (typeof EVENT_KINDS)[number];
|
|
104
106
|
/**
|
|
105
107
|
* The states of a plugin (docs/specs/plugins.md, "Lifecycle"): in the directory and loading;
|
package/dist/vocabulary.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vocabulary.d.ts","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vocabulary.d.ts","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"AAIA,qEAAqE;AACrE,eAAO,MAAM,WAAW,YACtB,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,MAAM,EACN,SAAS,CACD,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,EAAE,SAAS,SAAS,EAAkD,CAAC;AAEpG,mEAAmE;AACnE,eAAO,MAAM,eAAe,YAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAE5E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,WAAW,YAAI,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAE7E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,EAAE,SAAS,SAAS,EAA0B,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,WAAW,YACtB,MAAM,EACN,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,MAAM,EACN,QAAQ,CACA,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,qDAAqD;AACrD,eAAO,MAAM,eAAe,kFAAc,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC;AAEtC,+GAA+G;AAC/G,eAAO,MAAM,kBAAkB,YAAI,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,CAAU,CAAC;AAClG,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,+FAA+F;AAC/F,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,YAAI,IAAI,EAAE,IAAI,CAAU,CAAC;AAEvD,eAAO,MAAM,aAAa,YAAI,IAAI,EAAE,QAAQ,CAAU,CAAC;AAEvD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,WAAW,CAEpF;AAED,yFAAyF;AACzF,eAAO,MAAM,YAAY,YAAI,OAAO,EAAE,QAAQ,CAAU,CAAC;AAEzD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,eAAe,YAAI,QAAQ,EAAE,aAAa,CAAU,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,YAAI,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEhF,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,uFAAuF;AACvF,eAAO,MAAM,aAAa,YAAI,OAAO,EAAE,QAAQ,CAAU,CAAC;AAE1D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,yFAAyF;AACzF,eAAO,MAAM,oBAAoB,YAAI,WAAW,EAAE,SAAS,CAAU,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,YAAI,UAAU,EAAE,iBAAiB,CAAU,CAAC;AAE5E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,WAAW,YAAI,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEjE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,YAAI,SAAS,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAEhF,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,mGAAmG;AACnG,eAAO,MAAM,YAAY,YAAI,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC;AAE/F,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,+FAA+F;AAC/F,eAAO,MAAM,WAAW,YAAI,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC;AAExE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,qFAAqF;AACrF,eAAO,MAAM,YAAY,YAAI,UAAU,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,2EAA2E;AAC3E,eAAO,MAAM,cAAc,YAAI,MAAM,EAAE,MAAM,CAAU,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,eAAe,YAC1B,MAAM,EACN,OAAO,EACP,UAAU,EACV,QAAQ,EACR,WAAW,EACX,eAAe,EACf,aAAa,CACL,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,aAAa,YAAI,WAAW,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAEvE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,WAAW,YACtB,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,eAAe,CACP,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,aAAa,YACxB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,eAAe,EACf,UAAU,EACV,UAAU,CACF,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,YAAI,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAC;AAEvF,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/vocabulary.js
CHANGED
|
@@ -40,6 +40,8 @@ export const CATEGORY_COLORS = COLOR_NAMES;
|
|
|
40
40
|
/** The kinds of image a project's own mark may be: what a browser shows in place, and nothing that can run. */
|
|
41
41
|
export const PROJECT_ICON_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
42
42
|
/** The identity providers people may sign in through: the git host, and Google (Workspace). */
|
|
43
|
+
/** The languages the console's pages speak, and a plugin's words are given in. */
|
|
44
|
+
export const CONSOLE_LANGUAGES = ["en", "ko"];
|
|
43
45
|
export const PROVIDER_KEYS = ["gh", "google"];
|
|
44
46
|
export function isProviderKey(value) {
|
|
45
47
|
return PROVIDER_KEYS.includes(value ?? "");
|
|
@@ -114,6 +116,7 @@ export const EVENT_KINDS = [
|
|
|
114
116
|
"person.unlisted",
|
|
115
117
|
"person.deactivated",
|
|
116
118
|
"person.reactivated",
|
|
119
|
+
"person.manager_changed",
|
|
117
120
|
"workspace.updated",
|
|
118
121
|
"category.created",
|
|
119
122
|
"category.updated",
|
package/dist/vocabulary.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"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"}
|
package/docs/specs/cli.md
CHANGED
|
@@ -46,6 +46,7 @@ The board is a project's ([ADR-0008](../adr/0008-a-workspace-holds-projects-and-
|
|
|
46
46
|
| `workspace pack-token --stdin`, `workspace pack-token --remove` | `PUT /api/v1/workspace/pack-token` with the token read from standard input, or `DELETE /api/v1/workspace/pack-token` | the workspace's settings as they are now, saying when its SkillCDN token was set and never the token: what every project with no address and no token of its own reads the organization's pack with; for an administrator |
|
|
47
47
|
| `people` | `GET /api/v1/people` | one line per person the person sees (everyone, or, while the workspace narrows the people a member sees, those they share a project with and the administrators): login, name, role in the workspace, and `deactivated` for one taken out; then, where they see everyone, one line per login let in that nobody has signed in with yet. Needs no project |
|
|
48
48
|
| `person role <login> <admin\|member>` | `GET /api/v1/people?login=` for the id, then `PATCH /api/v1/people/<id>` | the person as they are now; for an administrator |
|
|
49
|
+
| `person manager <login> <manager login\|none>` | `GET /api/v1/people?login=` for both ids, then `PATCH /api/v1/people/<id>` with `managerId` | the person as they are now, with whom they report to: the reporting line of the directory, another active person who does not report to them, or none; for an administrator (`person.invalid_manager`); `console people` shows it beside each person |
|
|
49
50
|
| `person add <login> [--host gh\|google]`, `person remove <login>` | `POST /api/v1/listings`; `GET /api/v1/people` for the id, then `DELETE /api/v1/listings/<id>` | the login let in (the host read off the login unless `--host` says: an address is Google's, anything else the git host's), or that it is no longer; for an administrator ([ADR-0022](../adr/0022-who-is-in-is-the-consoles-own-record-and-an-administrator-keeps-it.md)) |
|
|
50
51
|
| `person deactivate <login>`, `person reactivate <login>` | `GET /api/v1/people?login=` for the id, then `PATCH /api/v1/people/<id>` with `status` | the person as they are now: out, refused on every request with their agents, or back in; for an administrator; never a person the organization let in |
|
|
51
52
|
| `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 |
|
|
@@ -59,7 +60,7 @@ The board is a project's ([ADR-0008](../adr/0008-a-workspace-holds-projects-and-
|
|
|
59
60
|
| `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 |
|
|
60
61
|
| `skills`, `skills <folder\|file>`, `skills --search <words> [<folder>] [--limit <n>] [--cursor <cursor>]` | `GET .../skills`; `GET .../skills/browse?path=&cursor=`, page after page to the end; `GET .../skills/find?query=&path=&cursor=&limit=`, one page | the project's pack, or the organization's ([ADR-0031](../adr/0031-the-console-reads-a-pack-as-the-skillcdn-command-does-and-a-local-one-from-a-directory.md)): where it is, at a deployment or on the console's machine, and how the read went; what a client is told of it on connect, as the deployment tells one, with the reads named as the console's commands; every skill with the path of its `SKILL.md` and every document, as a search without words lists them; where a person connects an agent of its own, and where the console's own skills are on this machine. With a folder (`.` for the root; `/` is taken too, but a Windows shell rewrites it into a path before the command sees it), what it holds, whole, as `browse_repo` lays it out for a model. With a file's path, the file's outline, whole: every heading with its level and the offset and limit that read its section with `skill --file`; a file that is not Markdown has none, and the line says so (SkillCDN 0.4). With `--search`, one page of what the words find, as `search_repo` does: skills first with the files of theirs that matched, then documents, each with the sections of it that matched and the offset and limit that read each, in relevance order, within the folder when one is named, ten unless `--limit` says otherwise (up to 25), a line on how the page was ranked where the deployment searches by meaning too, and a `nextCursor` line when more matched, which `--cursor` continues. `--json` is the console's answer: what the pack answered, in the shapes of the main repository's REST API, the pages of a folder or an outline joined. The listing ends with where the plugins' own skills are: `console plugin <key> skills` |
|
|
61
62
|
| `skill <path>`, `skill --file <path> [--offset <n>] [--limit <n>]` | `GET .../skills`, then `GET .../skills/one?path=&cursor=`, page after page until `complete`; with `--file`, `GET .../skills/file?path=&offset=` until the end, or, with `--offset` or `--limit`, `GET .../skills/file?path=&offset=&limit=` once | the skill whole, as `load_skill` lays it out for a model: the rules of the repository from its root to the nearest manifest, the instructions, the included files, then its supporting files and what it refers to, rendered by the main repository's own renderers with the reads named as the console's commands; or the file whole, or what a folder holds; or, with `--offset` (0 or more) or `--limit` (1 to 100,000), one page of the file as asked, the section a search or an outline named, with where the file continues; a private pack through the pack token the project holds ([ADR-0028](../adr/0028-the-console-reads-a-projects-pack-through-the-deployments-rest-api-with-a-pack-token-for-a-private-one.md)). `<path>` is the path of the SKILL.md from the repository's root, or the URI the pack names it by (`skill://<host>/<owner>/<name>/<path>`); a URI of another pack is not understood. `--file` takes no skill's path beside it, and `--offset` and `--limit` go with `--file` only: otherwise not understood. A read the pack refused prints its status and the pack's own words, and exits with `0` |
|
|
62
|
-
| `rules` | `GET .../rules`, or `GET /api/v1/rules` without a project named, and `GET /api/v1/me` | the rules that hold, as they read for the person (`{language}` is the language they
|
|
63
|
+
| `rules` | `GET .../rules`, or `GET /api/v1/rules` without a project named, and `GET /api/v1/me` | the rules that hold, as they read for the person (`{language}` is the language they read in, or the task's while they have none) ([ADR-0023](../adr/0023-the-rules-of-a-board-are-pages-the-workspace-and-its-projects-keep-read-first-by-every-agent.md)): the workspace's, the console's own until an administrator writes the organization's, with its version and who wrote it when written; then this project's own, or that it adds none; then, under `## Plugins`, a line per plugin bound to the project that the person holds a role in, or at the workspace every plugin they may use, with the sentence its manifest gives agents and `console plugin <key>` to start with ([plugins.md](plugins.md), "The command") |
|
|
63
64
|
| `rules write --body <markdown>\|--file <path>\|-\|none [--workspace] [--base <version>]` | `PUT .../docs/rules` or `POST .../docs/rules/archive`; with `--workspace`, `PUT /api/v1/rules` or `POST /api/v1/rules/archive` | the version written, that the console's own rules sent as they are wrote nothing, or that the rules are put away; for an owner of the project, or an administrator for the workspace's |
|
|
64
65
|
| `plugins` | `GET /api/v1/plugins`, `GET /api/v1/me` | one line per plugin the person may use ([plugins.md](plugins.md)): key, name in their language, version, state, their roles in it. Needs no project |
|
|
65
66
|
| `plugin <key>` | `GET /api/v1/plugins/<key>`, `GET /api/v1/me` | the plugin whole: what it is, the sentence for agents, the roles held in it, its board project, a line per command and query the person may run with its usage, where its skills are, its settings |
|
|
@@ -67,13 +68,13 @@ The board is a project's ([ADR-0008](../adr/0008-a-workspace-holds-projects-and-
|
|
|
67
68
|
| `plugin <key> <command> [<args>] [--<name> <value>]... [--file <path> \| -] [--run <id>]` | `POST /api/v1/plugins/<key>/files` as a form, where `--file` or `-`; then `POST /api/v1/plugins/<key>/invoke` with the words as typed after the command's name, the handle, the project the command works in and the run named | what the command says, or a query's answer as JSON, a file a query answers saved under its name; `--json` the whole answer; exit `3` with the decision's id and `console decision <id> --wait 100` when the command raised one; the console's refusal with its code otherwise. `--json`, `--url`, `--account`, `--project`, `--file` and `--run` are the command's own wherever they stand; every other word is the plugin's, and the console parses them against the definition |
|
|
68
69
|
| `plugin <key> records <collection> [<id>] [--where <field>=<value>]... [--search <words>] [--project <key>] [--order <field>[:desc]] [--limit <n>] [--after <cursor>] [--archived] [--versions]` | `GET .../records/<collection>?where=&q=&project=&order=&limit=&after=&archived=`; `GET .../records/<collection>/<id>`, `.../versions` | the records the person may read, one a line with the data compact, and the cursor the next page is asked with; one record whole; its versions |
|
|
69
70
|
| `plugin <key> skills [<folder>\|<file>] [--search <words>]`, `plugin <key> skill <path>`, `plugin <key> skill --file <path> [--offset <n>] [--limit <n>]` | `GET /api/v1/plugins/<key>/skills`, `.../skills/one`, `.../skills/file`, `.../skills/browse`, `.../skills/find`, as `skills` and `skill` ask a project's | the plugin's own skills, a pack read from its package, printed exactly as `skills` and `skill` print a project's |
|
|
70
|
-
| `plugin <key> enable --consent <capability>,... [--board new\|<key>] [--projects all\|<key>,...] [--set <key>=<value>]...`, `plugin <key> disable`, `plugin <key> settings [--set <key>=<value>]...`, `plugin <key> secret <name> [--remove]`, `plugin <key> grant <role> --person <login>\|--project <key>\|--everyone`, `plugin <key> revoke <grant id>` | `GET /api/v1/plugins/<key>` first; then `POST .../enable`, `POST .../disable`, `PATCH .../settings`, `PUT` or `DELETE .../secrets/<name>` with the value read from standard input, `GET /api/v1/people?login=` then `POST .../grants`, `DELETE .../grants/<id>` | for an administrator: `enable` prints what each capability the plugin asks opens and refuses unless `--consent` names every one again, makes the board project the manifest proposes with `--board new` or chooses one by key, puts the plugin on every project or on the keys named, and sets the settings read as their types, an empty value clearing one; what changed, as it is now; a secret is sealed and shown never |
|
|
71
|
+
| `plugin <key> enable --consent <capability>,... [--board new\|<key>] [--projects all\|<key>,...] [--set <key>=<value>]...`, `plugin <key> disable`, `plugin <key> capabilities [--consent <capability>,...\|none]`, `plugin <key> settings [--set <key>=<value>]...`, `plugin <key> secret <name> [--remove]`, `plugin <key> grant <role> --person <login>\|--project <key>\|--everyone`, `plugin <key> revoke <grant id>` | `GET /api/v1/plugins/<key>` first; then `POST .../enable`, `POST .../disable`, `PATCH .../consent`, `PATCH .../settings`, `PUT` or `DELETE .../secrets/<name>` with the value read from standard input, `GET /api/v1/people?login=` then `POST .../grants`, `DELETE .../grants/<id>` | for an administrator: `enable` prints what each capability the plugin asks opens and refuses unless `--consent` names every one again, makes the board project the manifest proposes with `--board new` or chooses one by key, puts the plugin on every project or on the keys named, and sets the settings read as their types, an empty value clearing one; what changed, as it is now; a secret is sealed and shown never |
|
|
71
72
|
| `take <number\|id> [--agent <name>]` | `GET .../tasks/<ref>`, then `POST .../runs`, then `GET .../rules`, `GET /api/v1/me`, `GET .../tasks/<ref>` again, `GET .../tasks/<id>/comments` and `GET .../runs?open=true&mine=true` | the run that began, with the run's id and the task's id on a line of their own, the task in full as it stands taken with the discussion on it, the rules that hold as they read for the person, with the plugins bound to the project under `## Plugins` as `rules` prints them, and what to do next; a run open on the task is taken over, and that is said when it happened ([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)); another run of the token open in the project is named, with the `--run <id>` to say on every command on a run from here |
|
|
72
73
|
| `report <markdown> [--run <id>]`, `report --file <path> [--run <id>]`, `report - [--run <id>]` | `POST .../runs/<id>/reports` | how many reports the run carries |
|
|
73
74
|
| `hand-in <https url \| file path> [--label <words>] [--run <id>]` | `POST .../runs/<id>/artifacts` for a link; `POST .../runs/<id>/files` for a file, sent as a form with its name and its media type by extension | how many artifacts; a picture handed in is shown on the task, and where a report names it as `` |
|
|
74
75
|
| `comment <number\|id> "<markdown>" [--attach <path>]...`, `comment <number\|id> --file <path>`, `comment <number\|id> -` | `GET .../tasks/<ref>`, then `POST .../tasks/<id>/comments`: as JSON, or as one form with the part `body` and a part `file` per file attached, its media type by extension | the comment as written, with its files and the command that reads each; a word to the task's people, which needs no run ([ADR-0024](../adr/0024-a-task-carries-a-discussion-of-comments-with-their-files-read-as-one-thread-with-the-runs-and-the-decisions.md)) |
|
|
75
76
|
| `file <id> [--out <path>]` | `GET .../files/<id>` | that the file is saved, where, with its size and type: under its own name in the working directory, at the path, or into the directory named; a file a run handed in, one put in a comment, or one attached to a page, so that an agent looks at a picture a person put on the board |
|
|
76
|
-
| `ask "<question>" --option "<label>" ... [--body <markdown>\|--file <path>] [--to <login\|me>] [--wait <seconds>] [--run <id>]` | `POST .../decisions` with `runId` and, for `--to`, `deciderId`, then `GET .../decisions/<id>?wait=` | the decision raised, its id on a line of its own, whom it waits for, its options; then the answer, or that it still waits. It is for the person the agent works for unless `--to` names another of the project ([ADR-0042](../adr/0042-a-decision-is-addressed-to-a-person-its-raiser-unless-another-is-named.md)) |
|
|
77
|
+
| `ask "<question>" --option "<label>" ... [--body <markdown>\|--file <path>] [--attach <path>]... [--to <login\|me>]... [--wait <seconds>] [--run <id>]` | `POST .../decisions` with `runId` and, for `--to`, `deciderId`, and `deciderIds` beside it where `--to` was given more than once ([ADR-0057](../adr/0057-a-decision-may-be-addressed-to-several-people-and-the-first-answer-ends-it.md)); with `--attach`, as one form with the part `decision` and a part `file` per file, its media type by extension ([ADR-0055](../adr/0055-a-decision-carries-the-files-put-on-it-when-it-is-raised.md)); then `GET .../decisions/<id>?wait=` | the decision raised, its id on a line of its own, how many files came, whom it waits for, its options; then the answer, or that it still waits. It is for the person the agent works for unless `--to` names another of the project ([ADR-0042](../adr/0042-a-decision-is-addressed-to-a-person-its-raiser-unless-another-is-named.md)), or several, any of whom may answer, the first answer ending it |
|
|
77
78
|
| `decision <id> [--wait <seconds>]` | `GET .../decisions/<id>`, with `?wait=` while waiting | the decision; with a wait, the answer or that it still waits |
|
|
78
79
|
| `answer <id> --option <n>\|--own "<answer>" [--note <markdown>\|--file <path>]` | `POST .../decisions/<id>/answer` | the decision with its answer: a person's answer written in their name through the agent, as they gave it in chat or in passing, with where and when in the note, so that the record is whole and a run that waited goes on ([ADR-0042](../adr/0042-a-decision-is-addressed-to-a-person-its-raiser-unless-another-is-named.md)) |
|
|
79
80
|
| `decisions [--open] [--limit <n>] [--offset <n>]`, `decisions --mine\|--raised [--open] [--limit <n>] [--offset <n>]` | `GET .../decisions`; `GET /api/v1/decisions` for `--mine`, with `raised=true` for `--raised`, neither needing a project | one line per decision, the waiting first; with `--mine`, the decisions addressed to the person across the projects they may see, with `--raised` those they asked of someone else, each with its project's key; a page at a time |
|
package/docs/specs/plugins.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
| plugin | One npm package that adds a feature to a console: commands and queries for agents, pages and widgets for people, records, jobs, hooks and skills; identified by its `key` |
|
|
11
11
|
| manifest | `console-plugin.json` at the package root: what the plugin is and asks, as data read without running anything |
|
|
12
12
|
| host | The console's child process that runs plugin code, one per `api` and `worker` role, with a thread per plugin |
|
|
13
|
-
| capability | Something a plugin asks of the console in its manifest and an administrator consents to when enabling it; the only way plugin code reaches the console |
|
|
13
|
+
| capability | Something a plugin asks of the console in its manifest, required or optional, and an administrator consents to when enabling it; the only way plugin code reaches the console |
|
|
14
14
|
| role | A name a plugin gives to what a person may do with it, granted by an administrator |
|
|
15
15
|
| board project | The project a plugin's decisions, tasks and documents go to, made or chosen when it is enabled |
|
|
16
16
|
| record, collection | A plugin's data, kept by the console: a collection is declared with a schema, a record is one document in it |
|
|
@@ -46,19 +46,22 @@
|
|
|
46
46
|
| `name`, `description` | `{ [language]: string }` | `en` required; a name up to 40 characters, a description up to 200 |
|
|
47
47
|
| `agentNote` | `{ [language]: string }` | one sentence for agents, up to 200 characters: what the plugin is for and when to use it; printed with the rules |
|
|
48
48
|
| `pluginApi` | integer | the major of the plugin API the plugin was written against; `1` |
|
|
49
|
+
| `console` | range | the consoles the plugin runs on, a semver range of the console's version as `requires` spells one (`>=0.4.3 <0.6`; a partial version is read with zeros filled in); left out, any console that serves `pluginApi`. A console outside it fails the plugin at discovery, saying the range and its own version, and answers the range on `GET /api/v1/plugins`; `console-plugin init` writes the line of the version the plugin is written against |
|
|
49
50
|
| `server` | path | the server module, relative to the package root |
|
|
50
51
|
| `web` | path | the directory of the web bundle, with `index.js`; required where `pages` or `widgets` are declared |
|
|
51
52
|
| `skills` | path | the directory of the skills; `SKILLCDN.md` is then at the package root |
|
|
52
53
|
| `migrations` | path | the directory of SQL migrations; with `storage:sql` only |
|
|
53
|
-
| `capabilities` | string[] | from the catalogue below; `outbound:<host>` and `plugins:<key>` carry their parameter |
|
|
54
|
+
| `capabilities` | string[] | what the plugin requires, from the catalogue below; `outbound:<host>` and `plugins:<key>` carry their parameter, `outbound:webrtc` is a word of its own |
|
|
55
|
+
| `optionalCapabilities` | string[] | what it can go without ([ADR-0060](../adr/0060-what-a-plugin-asks-is-required-or-optional-and-the-optional-are-the-administrators-to-choose.md)): the same catalogue, never `storage:sql`, each named once across the two lists, at most 50 together; an administrator turns each on when enabling the plugin or later, off until then |
|
|
54
56
|
| `roles` | `{ [role]: { name, description } }` | role keys as `key`; up to 10; names and descriptions per language |
|
|
55
57
|
| `defaultRole` | string | a role every member of the workspace holds without a grant; optional |
|
|
56
58
|
| `requires` | `{ [key]: range }` | other plugins this one needs, by a semver range of their version; they are enabled first and cannot be disabled while this one is |
|
|
57
59
|
| `board` | `{ needs, defaults? }` | `needs` is `required`, `optional` or `none`; `defaults` the `key`, `name` and `description` per language of the project an administrator may make for it |
|
|
58
|
-
| `settings` | Setting[] | up to 50, each `{ key, type, name, description?, required?, default?, min?, max?, options?, of? }`; `key` a lowercase letter followed by letters and digits (`daysPerYear`), as code and `--set` name it; types `text`, `markdown`, `number`, `boolean`, `enum` (with `options`, each `{ value, name }`), `day`, `person`, `project`, `secret`, `list` (with `of`, any type but `secret` and `list`); `min` and `max` bound a number, the length of a text or the items of a list; `default` fits the type, and `person`, `project` and `secret` have none |
|
|
60
|
+
| `settings` | Setting[] | up to 50, each `{ key, type, name, description?, required?, default?, min?, max?, options?, of? }`; `key` a lowercase letter followed by letters and digits (`daysPerYear`), as code and `--set` name it; types `text`, `markdown`, `number`, `boolean`, `enum` (with `options`, each `{ value, name }`), `day`, `time` (`HH:MM`, read in the workspace's time zone), `person`, `project`, `secret`, `list` (with `of`, any type but `secret` and `list`); `min` and `max` bound a number, the length of a text or the items of a list; `default` fits the type, and `person`, `project` and `secret` have none; `group` names one of `settingGroups`, under which the form shows the setting |
|
|
61
|
+
| `settingGroups` | Group[] | up to 10, each `{ key, name, description? }`, in the order the form shows them; the settings without a `group` come above them |
|
|
59
62
|
| `menu` | `{ group, order?, name? }` | the tab the plugin is under: a group of the console's (`people`, `customers`, `money`, `operations`, `marketing`, `engineering`, `reports`), or one the plugin declares with a `name` per language; `order` within the row, default 100 |
|
|
60
63
|
| `pages` | Page[] | up to 12, each `{ key, name, level, roles?, wide? }`; `level` is `workspace` or `project`; page keys as `key`, and not `frame`, `web` or `x` |
|
|
61
|
-
| `widgets` | Widget[] | up to 4, each `{ key, name, place,
|
|
64
|
+
| `widgets` | Widget[] | up to 4, each `{ key, name, place, sizes, defaultSize?, roles? }`; `place` is `home:top` or `home:bottom`; `sizes` the sizes the widget comes in, each once, among `small` (2×2 cells of the front page's grid), `medium` (4×2), `large` (4×4), `wide` (8×2) and `full` (8×4), at least one of them `small`, `medium` or `large`, since a phone's grid is four cells across ([ADR-0062](../adr/0062-a-widget-comes-in-a-size-a-phone-can-hold.md)), and `defaultSize` the one it starts at, the first of them when left out ([ADR-0061](../adr/0061-the-front-page-is-one-grid-of-tiles-a-person-arranges-by-hand.md)); the one `size` of before, `third`, `half` or `full`, still reads, as `small`, `medium` or `wide` |
|
|
62
65
|
| `dataVersion` | integer | the version of the plugin's record shapes, from 1; raised with an entry in `upgrades` |
|
|
63
66
|
| `store` | object | `homepage`, `repository`, `keywords`, `icon`; the license is `package.json`'s |
|
|
64
67
|
|
|
@@ -133,7 +136,7 @@ export default definePlugin({
|
|
|
133
136
|
},
|
|
134
137
|
endpoints: {},
|
|
135
138
|
on: {
|
|
136
|
-
"console:decision.answered": async (ctx, event) => { /*
|
|
139
|
+
"console:decision.answered": async (ctx, event) => { /* event.data.optionKey says which option; about maps it to the request */ },
|
|
137
140
|
},
|
|
138
141
|
jobs: {
|
|
139
142
|
accrue: { about: "Adds the year's days on its first day.", every: "P1D", at: "02:00", async run(ctx) { /* ... */ } },
|
|
@@ -169,11 +172,11 @@ Everything a plugin does to the console is a call on `ctx`, which is a message t
|
|
|
169
172
|
| `ctx.caller` | `{ kind: "person" \| "console", person?, agent?, roles, run?, project? }`: in a command, a query or a person's endpoint, the person (`id`, `login`, `name`, `language`, `admin`), the agent's name where a token acts, their roles in this plugin, their open run in the board project if any, and the project the call is on; in a job, a hook, an upgrade or a webhook, `console`, with every role | nothing |
|
|
170
173
|
| `ctx.records(collection)` | the records of a collection, by its definition (typed from the schema) or by name: `create(data, { project?, owner? })`, `get(id)` (`null` when there is none), `update(id, patch, { baseVersion? })`, `archive(id)`, `restore(id)`, `list({ where?, order?, limit?, after?, project?, archived? })`, `search(words, { where?, limit?, project? })`, `aggregate({ where?, groupBy?, count?, sum?, min?, max? })`, `versions(id)`, `link(id, target)`, `unlink(id, target)`, `links(id)`, and `files(id)` with `attach(handle, { name?, type? })`, `list()` and `remove(fileId)`; `order` is `{ field, descending? }`; a refusal is thrown as a `PluginRefusal` with the console's code | nothing; `files` for the files |
|
|
171
174
|
| `ctx.sql` | `query(text, params)` and `transaction(async (tx) => ...)`, on the plugin's own role | `storage:sql` |
|
|
172
|
-
| `ctx.console.workspace()` | the workspace's name, languages, time zone and categories | nothing |
|
|
173
|
-
| `ctx.console.people` | `list({ q? })` and `get(id)`: the people the caller may see; everyone for a `console` caller, or with `people:read:all` | `people:read` |
|
|
175
|
+
| `ctx.console.workspace()` | the workspace's name, languages, time zone, the day its week begins on (`weekStart`: `auto`, `monday` or `sunday`) and categories | nothing |
|
|
176
|
+
| `ctx.console.people` | `list({ q? })` and `get(id)`: the people the caller may see, each with `managerId`, whom they report to in the directory or `null`, for a plugin to take as its default where it needs someone's manager, and `language`, what they read in or `null` until the pages have seen them; everyone for a `console` caller, or with `people:read:all` | `people:read` |
|
|
174
177
|
| `ctx.console.projects` | `list()`, `get(key)`, `members(key)`: the projects the caller may see; all with `projects:read:all` | `projects:read` |
|
|
175
178
|
| `ctx.console.tasks` | `list(project, filters)`, `get(project, number)`, `create(project, task)`, `update(project, number, patch)`, `comment(project, number, body)`: reading in the plugin's projects, creating there, changing and commenting its own | `board:read`; `board:tasks` |
|
|
176
|
-
| `ctx.console.decisions` | `list(project)`, `get(id)`, `ask(project, { question, body?, options, deciderId?, taskId?, about })`: `about` names the record the decision is for; there is no `answer` | `board:read`; `board:decisions` |
|
|
179
|
+
| `ctx.console.decisions` | `list(project)`, `get(id)`, `ask(project, { question, body?, options, deciderId?, deciderIds?, taskId?, about })`: `options` each `{ label, key? }`, the `key` spelled as a plugin's key is and given once, answered back as `optionKey` on `console:decision.answered`; `about` names the record the decision is for; there is no `answer` | `board:read`; `board:decisions` |
|
|
177
180
|
| `ctx.console.documents` | `list(project, folder)`, `read(project, path)`, `write(project, path, { title, body })` under `plugins/<key>/` | `board:read`; `board:documents` |
|
|
178
181
|
| `ctx.console.runs` | `list(project)`, `get(id)` | `board:read` |
|
|
179
182
|
| `ctx.events.emit(kind, data)` | an event of the plugin's own, for its frames and for other plugins' hooks; `kind` as `key`, `data` JSON up to 16 KiB | nothing |
|
|
@@ -181,7 +184,7 @@ Everything a plugin does to the console is a call on `ctx`, which is a message t
|
|
|
181
184
|
| `ctx.secrets` | `has(name)`, `sign(name, payload, algorithm)`, `verify(name, payload, signature, algorithm)` with `hmac-sha256`; never the value | nothing |
|
|
182
185
|
| `ctx.plugins.get(key)` | `{ version, api: { [name]: (input) => Promise<unknown> } }` of another plugin, the caller passed through | `plugins:<key>` |
|
|
183
186
|
| `ctx.log` | `info`, `warn` and `error` lines, written to the console's log with the plugin's key and the caller; up to 100 lines a minute | nothing |
|
|
184
|
-
| `ctx.now()`, `ctx.language`, `ctx.signal` | the time; the caller's language, `en` for `console
|
|
187
|
+
| `ctx.now()`, `ctx.language`, `ctx.signal` | the time; the caller's language, `en` for `console` and for a person the pages have not seen; the `AbortSignal` that fires at the bound | nothing |
|
|
185
188
|
|
|
186
189
|
What `ctx` never has, whatever the manifest asks: the environment, a connection of the console's to the database, a session or a token, a secret's value, another plugin's records or secrets, a way to answer a decision, to change a person, a role, a membership or a setting of the workspace, or to make a request a person could not make themselves.
|
|
187
190
|
|
|
@@ -195,8 +198,8 @@ Declared in the manifest, consented to by an administrator when enabling, enforc
|
|
|
195
198
|
|---|---|---|
|
|
196
199
|
| (none) | its own records, versions, links and events; its settings; its log | its own data, spoiled; the versions restore it |
|
|
197
200
|
| `files` | files on its records, within `PLUGIN_FILE_BYTES_AT_MOST` | storage filled to the bound |
|
|
198
|
-
| `people:read` | the people the caller may see, as the person | the names and
|
|
199
|
-
| `people:read:all` | everyone, for `console` callers too | the directory |
|
|
201
|
+
| `people:read` | the people the caller may see, as the person, and among them who was granted a role of the plugin (`ctx.console.people.granted(role)`, an administrator listed only where granted it) and, for a frame, their pictures | the names, logins and pictures its role holders may see anyway |
|
|
202
|
+
| `people:read:all` | everyone, for `console` callers too; and the workspace's people events (`person.joined`, `person.deactivated`, `person.reactivated`, `person.role_changed`, `person.manager_changed`, `person.listed`, `person.unlisted`) to its hooks, with their content | the directory, and when people come and go |
|
|
200
203
|
| `projects:read` | the projects and members the caller may see | what the person sees |
|
|
201
204
|
| `projects:read:all` | every project and its members | the projects and who is in them |
|
|
202
205
|
| `board:read` | the tasks, decisions, runs, documents and events of its board projects, and of the project a call is on | the content of those boards, to its role holders |
|
|
@@ -207,11 +210,12 @@ Declared in the manifest, consented to by an administrator when enabling, enforc
|
|
|
207
210
|
| `events:plugins` | hooks on the events other plugins emit | what they publish |
|
|
208
211
|
| `jobs` | runs on a schedule | time, within the bound |
|
|
209
212
|
| `outbound:<host>` | `ctx.fetch` to that host, a public address, over https | what it may read, sent to that host; a cost there |
|
|
213
|
+
| `outbound:webrtc` | WebRTC on its pages: connections from each person's browser to any address ([ADR-0066](../adr/0066-webrtc-is-a-way-out-a-plugin-asks-for-and-how-a-frame-is-held-stays-in-one-place.md)) | what its pages are shown, sent anywhere from the person's browser; their address |
|
|
210
214
|
| `endpoints` | inbound requests under its path, a person's or a webhook's | input it accepts without verifying; the rate limit holds |
|
|
211
215
|
| `plugins:<key>` | that plugin's `api`, as the caller | what that API gives the caller |
|
|
212
216
|
| `storage:sql` | a schema and a login role of its own | statements up to the timeout, within its schema |
|
|
213
217
|
|
|
214
|
-
`outbound:<host>` names a host exactly or as `*.example.com`; the console resolves the host before connecting and refuses its own networks, as it does for a picture ([ADR-0048](../adr/0048-a-picture-from-elsewhere-is-read-through-the-console-from-a-public-address-and-kept-a-while.md)). A new version of a plugin that
|
|
218
|
+
`outbound:<host>` names a host exactly or as `*.example.com`; the console resolves the host before connecting and refuses its own networks, as it does for a picture ([ADR-0048](../adr/0048-a-picture-from-elsewhere-is-read-through-the-console-from-a-public-address-and-kept-a-while.md)). A new version of a plugin that requires a capability its install was not consented to waits, disabled, as `needs consent`, until an administrator consents again; a new optional capability waits for nothing, and stays off until one is turned on. `ctx.plugin.capabilities` says what the plugin holds, so that it offers what it can do; a page asks its own server.
|
|
215
219
|
|
|
216
220
|
## Roles and grants
|
|
217
221
|
|
|
@@ -223,7 +227,7 @@ Declared in the manifest, consented to by an administrator when enabling, enforc
|
|
|
223
227
|
|
|
224
228
|
## Settings
|
|
225
229
|
|
|
226
|
-
The form on `/settings/plugins/<key>` and `console plugin <key> settings --set` come from the manifest's `settings`. A `secret` is sealed with the deployment's secret (`AUTH_SECRET`, with the purpose `plugin-secret`), never returned by any route or shown in any form (only whether and when it was set), and used by the console where the plugin names it: `ctx.fetch`'s `secret`, `ctx.secrets.sign` and `verify`, a webhook's `secret`. A deployment without `AUTH_SECRET` refuses settings of type `secret`. `person` and `project` settings hold ids and are shown as names, chosen on the page among the workspace's people and projects; a person who left or a project put away makes the setting invalid, which the pages show. Settings are the workspace's; a plugin that needs a value per project keeps a record linked to the project.
|
|
230
|
+
The form on `/settings/plugins/<key>` and `console plugin <key> settings --set` come from the manifest's `settings`. A `secret` is sealed with the deployment's secret (`AUTH_SECRET`, with the purpose `plugin-secret`), never returned by any route or shown in any form (only whether and when it was set), and used by the console where the plugin names it: `ctx.fetch`'s `secret`, `ctx.secrets.sign` and `verify`, a webhook's `secret`. A deployment without `AUTH_SECRET` refuses settings of type `secret`. `person` and `project` settings hold ids and are shown as names, chosen on the page among the workspace's people and projects; a person who left or a project put away makes the setting invalid, which the pages show. A `time` is `HH:MM`, read in the workspace's time zone, which the form says beside it. A `list` has a control for its kind of item: a list of an `enum` is a pill per choice (a column of boxes past eight), a list of `person` or `project` the chips of those chosen with one choice to add another, a list of anything else the items as chips with a field that adds one, `min` and `max` bounding how many; `--set` takes a list with commas between, as before. The form is divided into the `settingGroups` the manifest declares, a titled block each in the manifest's order, the settings without a group above them. Settings are the workspace's; a plugin that needs a value per project keeps a record linked to the project.
|
|
227
231
|
|
|
228
232
|
## Records
|
|
229
233
|
|
|
@@ -244,7 +248,8 @@ With `storage:sql` consented to, enabling creates the schema `plugin_<key>` and
|
|
|
244
248
|
- `board.needs` says whether the plugin puts things on a board. Enabling one with `required` or `optional`, the administrator makes a project from `board.defaults` (the key, name and description in the workspace's languages, edited as they like; private; they are its owner) or chooses one that exists; several plugins may bind to one project. The install keeps the project's id, and the project's settings page shows the plugins bound to it.
|
|
245
249
|
- A plugin with `level: project` pages, or with `project: optional` or `required` collections, is on the projects the administrator names: all, or a list. A plugin on no project has no project pages. Owners do not enable plugins in their projects.
|
|
246
250
|
- What a plugin makes on a board carries its name: the console writes the link (`plugin_links`: plugin, kind, id) when `ctx.console.tasks.create`, `decisions.ask` or `documents.write` runs, the event carries `plugin = <key>` beside `actor` and `agent`, and the pages and the feed say "through <plugin>" (`plugin` on a task, a decision and a document as the API answers them). A person's call acts as the person; a `console` caller, a job or a hook, acts as the administrator who enabled the plugin, who owns what it makes, within the plugin's projects alone. A plugin changes, closes, comments or reads the answer of its own items only; it reads every item of its board projects with `board:read`. Its documents go under `plugins/<key>/`; a write elsewhere is `plugin.forbidden`.
|
|
247
|
-
- A decision a plugin raises is a decision as any ([ADR-0042](../adr/0042-a-decision-is-addressed-to-a-person-its-raiser-unless-another-is-named.md)): addressed to the person named in `deciderId`,
|
|
251
|
+
- A decision a plugin raises is a decision as any ([ADR-0042](../adr/0042-a-decision-is-addressed-to-a-person-its-raiser-unless-another-is-named.md)): addressed to the person named in `deciderId`, or to the several named in `deciderIds`, any of whom may answer and the first answer ending it ([ADR-0057](../adr/0057-a-decision-may-be-addressed-to-several-people-and-the-first-answer-ends-it.md)), each able to work in the project, else to the administrator who enabled the plugin; answered by anyone of the project; shown among each person's decisions and in `console work`. The command that raised it returns `waiting` and exits with `3`, and the agent waits as it does for `ask`. The plugin learns of the answer through `on["console:decision.answered"]`, which `about` lets it map to its record, and whose `data` names the chosen option by its label (`option`) and by the key the plugin gave it (`optionKey`), for its own decisions with `board:decisions` alone, so that it reads the answer without comparing labels or asking again; the person's own answer has no key. A plugin never answers.
|
|
252
|
+
- What a plugin writes for people, a decision's question, body and labels, a task's title and body, a comment's body, is one text, in the language of whoever it is for ([ADR-0065](../adr/0065-a-plugin-writes-one-text-and-a-persons-language-is-kept-from-the-first-time-the-pages-see-them.md)). `ctx.console.people.get(id)` says a person's `language`: the one they chose, else the one the pages first saw them in, `null` until then, where the plugin decides, the first of `ctx.console.workspace().languages` by default. Where several may answer, it chooses one of them. Whoever else reads the text reads it as written, as with what a person writes.
|
|
248
253
|
- Where a record is linked to a project and the caller may work there, `ask` and `tasks.create` may name that project instead of the board project.
|
|
249
254
|
- Two plugins on one project do not collide: each edits its own, reads all, writes in its own folder; one refers to another's work by reading, or through the other's `api`.
|
|
250
255
|
|
|
@@ -252,7 +257,7 @@ With `storage:sql` consented to, enabling creates the schema `plugin_<key>` and
|
|
|
252
257
|
|
|
253
258
|
- New kinds of the console's events: `plugin.enabled`, `plugin.disabled`, `plugin.configured`, `plugin.granted`, `plugin.revoked`, `plugin.upgraded`, `plugin.command`, `plugin.failed`, `plugin.purged`. `events.plugin` names the plugin on every event a plugin caused, its own kinds and the board's. `plugin.command` records the plugin, the command, the arguments (the secret ones as `[hidden]`), the outcome (`ok`, `refused` with its code, `waiting`, `failed`), the duration and the caller's run. They are in the board project's feed where there is one, and always at `GET /api/v1/plugins/<key>/events`.
|
|
254
259
|
- A plugin's own events (`ctx.events.emit`, the kind named as a `key`, the data JSON up to 16 KiB) go to `plugin_events` (plugin, kind, data, at; 100,000 kept, for ninety days, the janitor sweeping the rest), reach the frames of that plugin that subscribed, read at `GET .../plugin-events?after=&limit=` by its role holders, and the hooks of plugins with `events:plugins` on `plugin:<key>:<kind>`. They are not the board's feed.
|
|
255
|
-
- Hooks run in the `worker` role's host. A dispatcher reads the console's events and `plugin_events` from a cursor per plugin (`plugin_cursors`, begun at the end of both streams when the plugin is enabled, so that it is not told of everything that ever happened) under an advisory lock, so that one process dispatches, and delivers each event to the handler that named its kind; a console event is delivered for the plugin's board project, the projects it is on, the items it made and what it caused, with the kind, the ids and the time, and the content and the actor with `board:read
|
|
260
|
+
- Hooks run in the `worker` role's host. A dispatcher reads the console's events and `plugin_events` from a cursor per plugin (`plugin_cursors`, begun at the end of both streams when the plugin is enabled, so that it is not told of everything that ever happened) under an advisory lock, so that one process dispatches, and delivers each event to the handler that named its kind; a console event is delivered for the plugin's board project, the projects it is on, the items it made and what it caused, and, for a plugin with `people:read:all`, the workspace's people events (`person.*`), with the kind, the ids and the time, and the content and the actor with `board:read`, or with `people:read:all` for a people event, since the directory is its to read. Delivery is at least once and in order: a handler that fails is retried five times with doubling backoff, then the event is skipped with a `plugin.failed` event; a handler has thirty seconds.
|
|
256
261
|
- Jobs run in the `worker` role's host, with the `jobs` capability, each under an advisory lock, never two at once; `plugin_jobs` keeps the last run, its outcome and the next time, the first run one period after the scheduler first sees the job, `at` read in the workspace's time zone; a failed job is a `plugin.failed` event, at most one an hour per job, and a line in the log every time. A job has five minutes.
|
|
257
262
|
- `WORKER_IN_PROCESS` puts hooks and jobs in the `api` role's host.
|
|
258
263
|
|
|
@@ -267,7 +272,7 @@ With `storage:sql` consented to, enabling creates the schema `plugin_<key>` and
|
|
|
267
272
|
| State | How it comes about | What works |
|
|
268
273
|
|---|---|---|
|
|
269
274
|
| installed | the package is in `PLUGINS_DIR` with a manifest, and loads | listed in the settings; nothing else |
|
|
270
|
-
| failed | the manifest is invalid, the key is taken, `pluginApi` is not served, `requires` names a plugin that is missing, the server module does not load, or the installed `dataVersion` is newer than the code's | listed with its reasons; a `plugin.failed` event; the console boots on |
|
|
275
|
+
| failed | the manifest is invalid, the key is taken, `pluginApi` is not served, the console is outside `console`, `requires` names a plugin that is missing, the server module does not load, or the installed `dataVersion` is newer than the code's | listed with its reasons; a `plugin.failed` event; the console boots on |
|
|
271
276
|
| enabled | an administrator consented to the capabilities, bound the board, named the projects and filled the required settings, and `onEnable` ran | everything |
|
|
272
277
|
| needs consent | a new version asks capabilities the install lacks | nothing but the settings, until consented |
|
|
273
278
|
| disabled | an administrator disabled it and `onDisable` ran, or a required plugin is gone | nothing; the data kept; the tabs gone; commands `plugin.disabled` |
|
|
@@ -279,7 +284,7 @@ Upgrades: the `migrate` role, before the `api` and `worker` roles start on a new
|
|
|
279
284
|
## The host
|
|
280
285
|
|
|
281
286
|
- The `api` and `worker` roles each spawn one child process from the console's own code (`dist/plugin-host.js`), as `node --permission --allow-fs-read=<PLUGINS_DIR>,<each plugin's directory>,<the host's own directory> --allow-worker dist/plugin-host.js`, with an environment of nothing but what Node needs, no database credentials, and no configuration but what the parent sends over the IPC channel: the plugins to load and the limits. A plugin's directory is its real path, so a package linked into `PLUGINS_DIR` from a checkout, as it is while a plugin is written, is read where it is. No `--allow-fs-write`, `--allow-child-process`, `--allow-addons` or `--allow-wasi`.
|
|
282
|
-
- The host loads each plugin's server module in a worker thread of its own, with `resourceLimits` from `PLUGIN_MEMORY_MB_AT_MOST`, after hardening the thread: a module hook refuses `node:net`, `node:http`, `node:https`, `node:http2`, `node:tls`, `node:dgram`, `node:dns`, `node:child_process`, `node:cluster`, `node:worker_threads`, `node:vm`, `node:inspector`, `node:repl`, `node:wasi` and `node:v8
|
|
287
|
+
- The host loads each plugin's server module in a worker thread of its own, with `resourceLimits` from `PLUGIN_MEMORY_MB_AT_MOST`, after hardening the thread: a module hook refuses `node:net`, `node:http`, `node:https`, `node:http2`, `node:tls`, `node:dgram`, `node:dns`, `node:child_process`, `node:cluster`, `node:worker_threads`, `node:vm`, `node:inspector`, `node:repl`, `node:wasi` and `node:v8`, as well as the names Node keeps for compatibility that reach the same network (`node:_http_client` and its kin, `node:_tls_wrap`), by whichever way they are asked for, `process.getBuiltinModule` too; `globalThis.fetch`, `WebSocket`, `EventSource` and `process.binding` are removed; `process.env` is emptied. Reading files is the plugin's own directory, by the permission model; writing is nowhere.
|
|
283
288
|
- The host's main thread is the broker: a call on `ctx` is a message from the thread to the broker to the parent, which decides and performs it and answers; messages are JSON up to 4 MiB, and files travel as handles the parent resolves.
|
|
284
289
|
- A thread that runs past its time (`ctx.signal` fires first, then the broker ends it), grows past its memory or crashes is ended alone; the broker starts it afresh, and the call that was running fails as `plugin.timeout` or `plugin.unavailable`. Module-level state does not survive; state is in records.
|
|
285
290
|
- A host that dies is restarted by its parent; while it is away, every plugin call is `plugin.unavailable`, and the console answers everything else.
|
|
@@ -291,10 +296,11 @@ Under `/api/v1/plugins`. Who may call: *anyone* signed in or on a token, *roles*
|
|
|
291
296
|
|
|
292
297
|
| Route | Who | What |
|
|
293
298
|
|---|---|---|
|
|
294
|
-
| `GET /api/v1/plugins` | anyone | the plugins a member may know of (the enabled ones; every state for an administrator): key, name, description, version, state and reasons, the caller's roles, the menu, the pages and widgets the caller may see, the board project's key; and whether `storage:sql` is available in this deployment |
|
|
299
|
+
| `GET /api/v1/plugins` | anyone | the plugins a member may know of (the enabled ones; every state for an administrator): key, name, description, version, the consoles it declares it runs on (`console`, or `null`), state and reasons, the caller's roles, the menu, the pages and widgets the caller may see, the board project's key; and whether `storage:sql` is available in this deployment |
|
|
295
300
|
| `GET /api/v1/plugins/<key>` | anyone | one plugin: the above, its commands and queries (name, about, args), its skills address, its settings without the secrets (whether each is set); for an administrator the consent, the grants and the projects |
|
|
296
301
|
| `POST .../enable` | admin | `{ consent: [...], board: { create: { key, name, description } } \| { project: "<key>" } \| null, projects: "all" \| [...], settings: {...} }` |
|
|
297
302
|
| `POST .../disable` | admin | |
|
|
303
|
+
| `PATCH .../consent` | admin | `{ consent: [...] }`: what an enabled plugin holds from now on, every capability it requires named again and the optional ones to keep on; a `plugin.configured` event with `capabilities` |
|
|
298
304
|
| `PATCH .../settings` | admin | `{ values }`, without secrets |
|
|
299
305
|
| `PUT .../secrets/<name>`, `DELETE .../secrets/<name>` | admin | `{ value }`; never read |
|
|
300
306
|
| `GET .../grants`, `POST .../grants`, `DELETE .../grants/<id>` | admin | `{ role, person?: id, project?: key, everyone?: true }` |
|
|
@@ -304,6 +310,7 @@ Under `/api/v1/plugins`. Who may call: *anyone* signed in or on a token, *roles*
|
|
|
304
310
|
| `GET .../records/<collection>?where=&order=&limit=&after=&q=&project=` | roles | the records the caller may read |
|
|
305
311
|
| `GET .../records/<collection>/<id>[?version=]`, `GET .../records/<collection>/<id>/versions` | roles | one record, a version of it, its versions |
|
|
306
312
|
| `POST .../files`, `GET .../files/<id>` | roles | a file for a command (a handle, good for an hour); a record's file |
|
|
313
|
+
| `GET .../people/<id>/picture` | roles, `people:read` | the picture of a person the asker may see, or of anyone with `people:read:all`; it names the person, never an address ([ADR-0063](../adr/0063-a-frame-reads-a-persons-picture-by-the-person-and-a-plugin-reads-who-it-granted-a-role.md)) |
|
|
307
314
|
| `GET .../events?limit=&offset=` | roles | the plugin's events |
|
|
308
315
|
| `GET .../plugin-events?after=&limit=` | roles | the events the plugin emitted (`ctx.events.emit`), after a number, oldest first: `{ items: [{ id, kind, data, at }], more }` |
|
|
309
316
|
| `GET .../skills`, `.../skills/one?path=&cursor=`, `.../skills/file?path=&offset=&limit=`, `.../skills/browse?path=&cursor=&limit=`, `.../skills/find?query=&path=&cursor=&limit=` | anyone who may know of the plugin | the plugin's skills, a pack of its own at `/local/plugins/<key>`, read from its package on the console's machine as a `local` pack is ([ADR-0031](../adr/0031-the-console-reads-a-pack-as-the-skillcdn-command-does-and-a-local-one-from-a-directory.md)), answered as a project's five reads are; `status: none` for a plugin that ships none |
|
|
@@ -311,7 +318,7 @@ Under `/api/v1/plugins`. Who may call: *anyone* signed in or on a token, *roles*
|
|
|
311
318
|
| `GET .../export` | admin | JSON Lines, and the list of the files |
|
|
312
319
|
| `POST .../purge` | admin | `{ confirm: "<key>" }` |
|
|
313
320
|
| `GET .../frame?page=<key>\|widget=<key>&project=<key>` | anyone, no session | the frame document |
|
|
314
|
-
| `GET .../web/<version>/<path>` | anyone, no session | a file of the bundle, immutable |
|
|
321
|
+
| `GET .../web/<version>/<path>` | anyone, no session | a file of the bundle, immutable; a script of a plugin that lists `outbound:webrtc` as optional is kept nowhere |
|
|
315
322
|
| `GET /api/v1/plugin-runtime/console.css` | anyone, no session | the console's stylesheet, for frames |
|
|
316
323
|
| `GET /api/v1/plugin-runtime/fonts.css` | anyone, no session | the faces of the console's own build, for frames; empty where the server has no build |
|
|
317
324
|
| `GET /api/v1/plugin-runtime/assets/<file>` | anyone, no session | a font of the console's build, immutable |
|
|
@@ -328,7 +335,7 @@ Under `/api/v1/plugins`. Who may call: *anyone* signed in or on a token, *roles*
|
|
|
328
335
|
| `plugin <key> <command> [args] [--<flag> <value>]... [--file <path> \| -] [--run <id>] [--json]` | `POST .../files` where `--file` or `-`, then `POST .../invoke` with the words as typed, the handle, the project the command works in and the run named | the command's `text`, or its `data` with `--json`; a query's answer as JSON, a file it answers saved under its name; exit `0`; `3` with `waiting`, printing the decision's id and `console decision <id> --wait`; `1` on a refusal, in the console's form. `--json`, `--url`, `--account`, `--project`, `--file` and `--run` are the command's own wherever they stand; every other word is the plugin's |
|
|
329
336
|
| `plugin <key> records <collection> [<id>] [--where <field>=<value>]... [--search <words>] [--project <key>] [--order <field>[:desc]] [--limit <n>] [--after <cursor>] [--archived] [--versions]` | `GET .../records/...` | the records, one a line, or one whole, or its versions |
|
|
330
337
|
| `plugin <key> skills [--search <words>]`, `plugin <key> skill <path>` | `GET .../skills...` | as `console skills` and `console skill` |
|
|
331
|
-
| `plugin <key> enable [--consent <capability>,...] [--board new\|<key>] [--projects all\|<key>,...] [--set <key>=<value>]...`, `plugin <key> disable`, `plugin <key> settings [--set ...]`, `plugin <key> secret <name>` (the value from standard input), `plugin <key> grant <role> --person <login>\|--project <key>\|--everyone`, `plugin <key> revoke <grant>` | the administrator's routes | what changed; `enable` prints what each capability opens before asking the console, and refuses without `--consent` naming every capability the manifest
|
|
338
|
+
| `plugin <key> enable [--consent <capability>,...] [--board new\|<key>] [--projects all\|<key>,...] [--set <key>=<value>]...`, `plugin <key> disable`, `plugin <key> capabilities [--consent <capability>,...|none]`, `plugin <key> settings [--set ...]`, `plugin <key> secret <name>` (the value from standard input), `plugin <key> grant <role> --person <login>\|--project <key>\|--everyone`, `plugin <key> revoke <grant>` | the administrator's routes | what changed; `enable` prints what each capability opens before asking the console, and refuses without `--consent` naming every capability the manifest requires; `capabilities` says what the plugin holds, and with `--consent` which of the optional ones it holds from now on |
|
|
332
339
|
|
|
333
340
|
The rules an agent reads carry the plugins: `GET /api/v1/rules` and `GET /api/v1/projects/<key>/rules` answer `plugins`, each with its `key`, `name`, `agentNote` and `description` by language and the caller's `roles` in it, and `console take` and `console rules` print, after the project's rules, a section `## Plugins` with a line per plugin bound to the project (as its board project, or on it) that the caller holds a role in, `- <key> (<name>): <agentNote> Start with console plugin <key>.`, the note in the caller's language where the manifest has it, the description where it has no note; `console rules` at the workspace lists every plugin the caller may use. Nothing else of a plugin reaches an agent unasked. `console help` names the two commands in a section of their own, and `console skills` ends with where a plugin's skills are. The skill `working-the-board` says: when the rules name a plugin, read `console plugin <key>` and its skills before its first command.
|
|
334
341
|
|
|
@@ -351,7 +358,7 @@ The rules an agent reads carry the plugins: `GET /api/v1/rules` and `GET /api/v1
|
|
|
351
358
|
</html>
|
|
352
359
|
```
|
|
353
360
|
|
|
354
|
-
with the headers `content-security-policy: default-src 'none'; script-src <origin>/api/v1/plugins/<key>/web
|
|
361
|
+
with the headers `content-security-policy: default-src 'none'; script-src <origin>/api/v1/plugins/<key>/web/<version>/; style-src <origin>/api/v1/plugins/<key>/web/ <origin>/api/v1/plugin-runtime/; img-src <origin>/api/v1/plugins/<key>/web/ data: blob:; font-src <origin>/api/v1/plugins/<key>/web/ <origin>/api/v1/plugin-runtime/; connect-src 'none'; frame-ancestors <origin>; base-uri 'none'; form-action 'none'; sandbox allow-scripts allow-forms`, `referrer-policy: no-referrer`, `x-content-type-options: nosniff` and `cache-control: no-store`. `<origin>` is the origin of the page that embeds the frame, read from the request's `referer`: `PUBLIC_URL`'s, or the loopback a person's own console is served on by `console serve` ([ADR-0014](../adr/0014-a-persons-own-console-is-served-from-their-machine-by-the-command.md)); any other, or none, is not found. A plugin that is not enabled, or a page or a widget it does not declare, is answered 404 with a blank document under `default-src 'none'; script-src 'sha256-<its one script>'; frame-ancestors <origin>; base-uri 'none'; form-action 'none'; sandbox allow-scripts`, whose one script tells the page `unavailable`, so that a frame never shows an answer meant for a program. The console's page embeds the frame as `<iframe sandbox="allow-scripts allow-forms" referrerpolicy="origin" src=...>`. The document's origin is opaque: no cookie travels, the API is out of reach, and its scripts are the bundle's alone. `allow-forms` is there so that a page's form fires its `submit` event, which a browser drops with the submission otherwise; `form-action 'none'` keeps a submission from going anywhere, so a page handles the event itself and speaks over the bridge. The headers are proven by an integration test, and a browser is seen to enforce them by `pnpm test:browser`, a real Chromium against the console listening on this machine, apart from `pnpm check` (`apps/console/src/http/plugin-frame.browser.test.ts`). The files of the bundle, `GET .../web/<version>/<path>`, are served from the package's `web` directory with `cache-control: public, max-age=31536000, immutable`, `cross-origin-resource-policy: cross-origin` and `access-control-allow-origin: *`, since the frame's origin is not the console's and a module script, as a font, is fetched with CORS; the console's stylesheet for frames carries the same two. The document links `fonts.css` before the stylesheet: the `@font-face` rules of the console's own build, their files served at `GET /api/v1/plugin-runtime/assets/<file>`, fonts alone, so that a frame reads in the console's faces; empty where the server has no build. In a frame document the stylesheet paints no background and lets the document be as tall as its content (`html[data-console]`), so that the box the console draws shows through and the frame shrinks as well as grows. A bundle holds no secret, since anyone may fetch it. The console's own pages gain `frame-src 'self'` in their policy and nothing else.
|
|
355
362
|
|
|
356
363
|
### The bridge
|
|
357
364
|
|
|
@@ -359,42 +366,48 @@ The console's page and the frame speak over `postMessage`, every message `{ v: 1
|
|
|
359
366
|
|
|
360
367
|
| From | `t` | Carries |
|
|
361
368
|
|---|---|---|
|
|
362
|
-
| the page | `init` | `plugin: { key, version }`, `page` or `widget`, `project?: { key, name }`, `person: { id, login, name, language, admin }`, `roles`, `path` (what follows the page in the address), `language`, `theme: { [token]: value }` |
|
|
369
|
+
| the page | `init` | `plugin: { key, version }`, `page` or `widget` (with `size`, the size the widget has, [ADR-0059](../adr/0059-a-person-arranges-the-front-pages-widgets-from-the-sizes-each-comes-in.md)), `project?: { key, name }`, `person: { id, login, name, language, admin }`, `workspace: { name, languages, timeZone, weekStart, firstDay }` (`firstDay` the day a week begins on with the workspace's setting applied, 1 for Monday, 7 for Sunday, for a calendar to start from; none from a console older than it), `roles`, `path` (what follows the page in the address), `language`, `theme: { [token]: value }` |
|
|
363
370
|
| the page | `result` | `id`, `ok`, `value` or `error: { code, message }` |
|
|
364
371
|
| the page | `event` | `kind: "records" \| "command" \| "plugin"`, `data`: something of this plugin changed. `command` and `records` come from the project's feed, on every `plugin.command` of the plugin on the project the page is on; `plugin` from `GET .../plugin-events`, asked for every few seconds while a frame listens |
|
|
365
372
|
| the page | `theme` | the tokens, when the console's look changes |
|
|
366
373
|
| the page | `path` | `path`, when the console navigated within this page's address |
|
|
374
|
+
| the page | `size` | `size`, when the widget has another of the sizes it comes in: the person chose it, or the page's width changed the grid |
|
|
367
375
|
| the frame | `ready` | nothing; the page answers with `init` |
|
|
368
|
-
| the frame | `
|
|
376
|
+
| the frame | `unavailable` | nothing; the page shows a line of its own in place of the frame. The document the console serves when there is nothing to show says it: a plugin that is off, a page or a widget it has not |
|
|
377
|
+
| the frame | `call` | `id`, `method`, `params`: `command` (`name`, `args`), `query` (`name`, `args`), `records.list`, `records.get`, `records.versions`, `files.get` (`id`; the bytes come back transferred), `files.put` (`bytes`, `name`, `type`; a handle comes back), `people.picture` (`id` of a person; the bytes and their type come back transferred) |
|
|
369
378
|
| the frame | `navigate` | `path`: a path of the console's, which the page follows in place; a URL is refused |
|
|
370
|
-
| the frame | `resize` | `height`, which the page gives the
|
|
379
|
+
| the frame | `resize` | `height`, which the page gives a page's frame; a widget fills the cells its size gives it, and its height is not read |
|
|
371
380
|
| the frame | `title` | `text`, for the document's title |
|
|
372
381
|
| the frame | `download` | `id` of a file, which the page downloads |
|
|
373
382
|
| the frame | `subscribe` | `kinds`, to receive `event` |
|
|
374
383
|
|
|
375
384
|
The page performs every `call` with the person's session under `/api/v1/plugins/<key>/` only; a method or a path outside it is refused before any request, as `plugin.forbidden`. A page thus holds exactly the authority of its plugin's server module, as the person using it.
|
|
376
385
|
|
|
377
|
-
`@skillcdn/console/plugin/web` is the frame's side: `connect()` says `ready`, waits for `init`, and resolves to `{ context, call, command, query, records, files, navigate, download, setTitle, onEvent, onTheme, onPath, close }`, applies the tokens to `:root` and the language to the document, and watches the body's height; it depends on nothing, and a refusal arrives as a `PluginBridgeError` with the console's code. `@skillcdn/console/plugin/web/react` adds `usePlugin()` for a plugin that chooses React. A page renders nothing a person wrote as HTML, as the console's own pages do not.
|
|
386
|
+
`@skillcdn/console/plugin/web` is the frame's side: `connect()` says `ready`, waits for `init`, and resolves to `{ context, call, command, query, records, files, people, navigate, download, setTitle, onEvent, onTheme, onPath, close }`, applies the tokens to `:root` and the language to the document, and watches the body's height; it depends on nothing, and a refusal arrives as a `PluginBridgeError` with the console's code. `@skillcdn/console/plugin/web/react` adds `usePlugin()` for a plugin that chooses React. `people.picture(id)` answers a `blob:` address for an image, or `null` for a person with no picture to show. A page renders nothing a person wrote as HTML, as the console's own pages do not.
|
|
378
387
|
|
|
379
388
|
### Tabs, sub-tabs and addresses
|
|
380
389
|
|
|
381
390
|
- At the workspace, after the console's own tabs and the organization's pages, and before Settings, which is last, come the groups that hold a plugin the person has a role in; in a project the same, before the project's settings. A group with one plugin is a tab with the plugin's name, leading to its first page; a group with several is a tab with the group's name that opens the list of its plugins, each leading to its first page (a `<details>`, as the person's menu is; `NavItem.children`). The groups the console knows have names in every language pack; a group a plugin declares has the plugin's. Groups and plugins are ordered by `menu.order`, then by key.
|
|
382
|
-
- A plugin with several pages at a level has a row of sub-tabs the console draws above the frame, in the manifest's order; a page's `wide` widens the frame as `CustomPage.wide` does.
|
|
391
|
+
- A plugin with several pages at a level has a row of sub-tabs the console draws above the frame, in the manifest's order, joined to the header's tabs; a page's `wide` widens the frame as `CustomPage.wide` does. Views within a page are the plugin's own: `sc-subtabs` around `sc-tab`s, links or buttons, with `sc-tab-current` on the one shown, is the console's view switch.
|
|
383
392
|
- Addresses: `/plugins/<key>` is the first page, `/plugins/<key>/<page>` a page, `/plugins/<key>/<page>/<rest>` a page with `<rest>` handed to the frame as `path`; on a project, `/projects/<pkey>/plugins/<key>[/<page>[/<rest>]]`. The custom pages of a console keep `/pages/<key>` ([ADR-0010](../adr/0010-the-default-uis-addresses-name-what-they-show-and-every-page-and-form-has-one.md)).
|
|
384
393
|
- On a project, the tab row gains the same, for the plugins on that project with `level: project` pages, to the members who hold a role.
|
|
385
394
|
- A person without a role sees no tab, and a plugin's address answers not found, as a project they may not see does.
|
|
386
395
|
|
|
387
396
|
### Widgets
|
|
388
397
|
|
|
389
|
-
The front page (`/`)
|
|
398
|
+
The front page (`/`) is one grid of square cells on which the projects and the widgets stand as tiles ([ADR-0061](../adr/0061-the-front-page-is-one-grid-of-tiles-a-person-arranges-by-hand.md)): the widgets the person holds a role for, of the plugins that are enabled. The grid has 12 columns where the page is at least 1520 pixels wide, 8 from 900, 6 from 560 and 4 below, and a cell is as wide as that leaves it. A project is an `icon` of 1×1 cells or `small` of 2×2. A widget is at its size, `small` 2×2, `medium` 4×2, `large` 4×4, `wide` 8×2, `full` 8×4, filling the cells it has; the height it says is not read. A grid offers a tile the sizes that fit it, and one kept or started at a size too wide takes the largest it comes in that fits, each width being arranged for itself; every widget has a size at most four cells across, so that a phone has one to show ([ADR-0062](../adr/0062-a-widget-comes-in-a-size-a-phone-can-hold.md)). Each widget is a frame with the same document and bridge, `widget=<key>` in place of `page`, its name above it; `init` carries `size`, the size the widget has on this grid, and a `size` message follows when the person changes it or the page narrows past it, so that the bundle lays itself out for the cells (`frame.context.size`, `frame.onSize`).
|
|
399
|
+
|
|
400
|
+
There is no default layout. What the person has not seen yet takes the first room reading from the top, at the size it starts at: a project made since, the widgets of a plugin as soon as it is enabled. For someone who has arranged nothing, `home:top` puts a widget before the projects and `home:bottom` after them. `GET /api/v1/me` answers `home`, `{ hidden: [<tile>, ...], layouts: { "12"?, "8"?, "6"?, "4"?: [{ tile, x, y, size }, ...] } }`, or `null` while they have arranged nothing: the tiles they took off, which stay off, and what they arranged at each width, a tile being `project:<id>` or `widget:<plugin>:<widget>`; `PATCH /api/v1/me` with `home` keeps it. A width nobody arranged reads the same order packed from the top.
|
|
401
|
+
|
|
402
|
+
Edit layout opens nothing on the page. A tile is taken in hand with the mouse, or with a finger that rests on it a moment first, and put down on any cell; empty cells stay empty. Where it would land shows the tile, faint, and those in the way slide aside as it comes, the nearest first. On a tile of its own shape, the tiles of that shape between the two places each move one place towards the one it left; a smaller tile gives way to the nearest room, and a larger one stays, the tile landing beside it. The arrow keys move the tile with the focus a cell, and Delete takes it off. Each tile carries the way off the page and the sizes it comes in, what was taken off is listed to add back, Done keeps it all and Cancel lets it go. A tile the person may no longer see, for a role gone or a plugin disabled, is out of sight and comes back where it stood.
|
|
390
403
|
|
|
391
404
|
### The look
|
|
392
405
|
|
|
393
|
-
The console's page reads its computed `--sc-*` tokens (the list is `CONSOLE_TOKENS` in the package) and sends them in `init.theme` and in `theme`; the frame's SDK sets them on `:root`, so that a custom console's look reaches its plugins' pages. `GET /api/v1/plugin-runtime/console.css` is the package's `console.css`, so that the `sc-*` classes work in a frame. Tokens added to the console's set for plugins: `--sc-color-info` and `--sc-color-info-subtle`; `--sc-color-neutral` and `--sc-color-neutral-subtle`, a state neither good nor bad; `--sc-series-1` to `--sc-series-6`, a palette for figures; `--sc-numeric`, the font features for tabular numerals. A plugin's own classes begin with `pl-<key>-`; `console-plugin check` warns of others. The frame's `lang` is the person's language, and the console shows the manifest's names in it; the words inside the frame are the plugin's, from `init.language`.
|
|
406
|
+
The console's page reads its computed `--sc-*` tokens (the list is `CONSOLE_TOKENS` in the package) and sends them in `init.theme` and in `theme`; the frame's SDK sets them on `:root`, so that a custom console's look reaches its plugins' pages. `GET /api/v1/plugin-runtime/console.css` is the package's `console.css`, so that the `sc-*` classes work in a frame. Tokens added to the console's set for plugins: `--sc-color-info` and `--sc-color-info-subtle`; `--sc-color-neutral` and `--sc-color-neutral-subtle`, a state neither good nor bad; `--sc-series-1` to `--sc-series-6`, a palette for figures; `--sc-numeric`, the font features for tabular numerals. A plugin's own classes begin with `pl-<key>-`; `console-plugin check` warns of others. A page pads itself by `--sc-space-4` on every side, for the shadows of what is in it, which the frame would cut; the frame of a page stands that far outside the page's column, so that the page's first words line up with the tabs above it. A widget pads nothing: the box the console draws around it does. The frame's `lang` is the person's language, and the console shows the manifest's names in it; the words inside the frame are the plugin's, from `init.language`.
|
|
394
407
|
|
|
395
408
|
### The settings pages
|
|
396
409
|
|
|
397
|
-
The Settings page lists the plugins with their state, for an administrator, each leading to its own page, and `/settings/plugins` is that list alone; `/settings/plugins/<key>` is one, read at a glance and with as few words as it takes: its name, key, version and state in the head, with the way to disable it; why it cannot run, where it cannot; a row each for its board project, the projects it is on, the capabilities it holds, its commands and queries, and what agents read of it; where it is not enabled, the form that enables it, in three parts: the capabilities, each by the name the pages give it in the person's language with one sentence of what it opens (the packs' `plugins.capability`; the catalogue above is what they say),
|
|
410
|
+
The Settings page lists the plugins with their state, for an administrator, each leading to its own page, and `/settings/plugins` is that list alone; `/settings/plugins/<key>` is one, read at a glance and with as few words as it takes: its name, key, version and state in the head, with the way to disable it; why it cannot run, where it cannot; a row each for its board project, the projects it is on, the capabilities it holds, those it can go without each with a box to turn it on or off, its commands and queries, and what agents read of it; where it is not enabled, the form that enables it, in three parts: the capabilities, each by the name the pages give it in the person's language with one sentence of what it opens (the packs' `plugins.capability`; the catalogue above is what they say), in two lists: those it requires, on and not the administrator's to turn off, one a new version asks marked as new, and those it can go without, off until turned on, those consented to before on already; the board project, to make (the form filled from `board.defaults`) or to choose; the projects, all or some; the settings form from the manifest, and each secret with when it was set, never its value; the roles the plugin declares, each with what it is for and who holds it, every member for `defaultRole`, each grant (a person, a project's members, everyone) a chip with the way to revoke it, and one choice to grant the role to someone not holding it yet; the plugin's events; export and purge, the latter offered once the plugin is disabled and asking for the key to be typed. Administrators only; no plugin code runs on these pages.
|
|
398
411
|
|
|
399
412
|
## Security model
|
|
400
413
|
|
|
@@ -415,11 +428,11 @@ The install path is the first line (a release of the deployment, from a lockfile
|
|
|
415
428
|
| hold the console: run past its time, grow past its memory, send more than fits | the bounds; the thread ended alone |
|
|
416
429
|
| hide: run a command, change the board or fail without a trace | the events and the log |
|
|
417
430
|
|
|
418
|
-
**The reach, by capability,** is the last column of the catalogue above. In sum: a plugin reaches what its role holders may see through it and what its consented capabilities open; sending anything out needs an `outbound`
|
|
431
|
+
**The reach, by capability,** is the last column of the catalogue above. In sum: a plugin reaches what its role holders may see through it and what its consented capabilities open; sending anything out needs an `outbound` capability the administrator consented to; what it does on a board is marked and reversible.
|
|
419
432
|
|
|
420
433
|
**What is checked, not enforced.** The hardening of a thread is defence in depth: a sandbox of its own would be a host container without egress, left to later. `console-plugin check` scans a plugin for what the host refuses, so that an author learns before an administrator does.
|
|
421
434
|
|
|
422
|
-
**The pages.** A frame's code runs in an opaque origin and reaches the console through the bridge alone, which performs its plugin's own routes and nothing else; it holds the person's authority within its plugin, exactly as the plugin's server does. Nothing a plugin writes is rendered as HTML by the console's pages: a tab, a sub-tab and a widget's name are text.
|
|
435
|
+
**The pages.** A frame's code runs in an opaque origin and reaches the console through the bridge alone, which performs its plugin's own routes and nothing else; it holds the person's authority within its plugin, exactly as the plugin's server does. A file of its bundle, which a frame may go to, carries a policy of its own and runs nothing as a document. A frame holds no WebRTC either, which `connect-src` does not govern and no policy a browser honours closes: every script of a bundle is served beginning with a line that takes it out of wherever the script runs, the frame or a frame made inside it ([ADR-0064](../adr/0064-a-frame-holds-no-webrtc-every-script-of-a-bundle-begins-by-taking-it-out.md)). A plugin that holds `outbound:webrtc` is served its scripts without that line; no host opens it, and it opens no host. One that lists it as optional is served its scripts uncached, so that it is gone from the next time a frame loads once it is withdrawn; a consent a new version no longer asks opens nothing, and a frame runs its own version's scripts alone ([ADR-0066](../adr/0066-webrtc-is-a-way-out-a-plugin-asks-for-and-how-a-frame-is-held-stays-in-one-place.md)). Nothing a plugin writes is rendered as HTML by the console's pages: a tab, a sub-tab and a widget's name are text.
|
|
423
436
|
|
|
424
437
|
**The record.** Who did what, through which plugin, is on the board: `plugin.command` for every command, the board's own events with the plugin's key for every change, `plugin.enabled` and its kin for every administrative act. The settings page shows a plugin's events, and a feed is filtered by plugin. What was read, queried, received and run on schedule is in the operational log, a line each, with the plugin, the person, the name, the duration and the outcome.
|
|
425
438
|
|
|
@@ -436,7 +449,7 @@ The install path is the first line (a release of the deployment, from a lockfile
|
|
|
436
449
|
| outbound requests; an answer; its time | 60 a minute per plugin; 10 MiB; 10 s |
|
|
437
450
|
| webhook requests | 600 a minute per plugin |
|
|
438
451
|
| `ctx.log` | 100 lines a minute |
|
|
439
|
-
| collections; commands and queries; endpoints; pages; widgets; roles; settings; indexes of a collection | 50; 100; 20; 12; 4; 10; 50; 8 |
|
|
452
|
+
| collections; commands and queries; endpoints; pages; widgets; roles; settings; groups of settings; indexes of a collection | 50; 100; 20; 12; 4; 10; 50; 10; 8 |
|
|
440
453
|
| SQL: a statement; a result; connections | 10 s; 10,000 rows and 4 MiB; 4 |
|
|
441
454
|
| a page of a list | 200 |
|
|
442
455
|
|
|
@@ -459,11 +472,12 @@ The install path is the first line (a release of the deployment, from a lockfile
|
|
|
459
472
|
|
|
460
473
|
## Authoring
|
|
461
474
|
|
|
462
|
-
- `console-plugin init <dir> --key <key> [--name <name>] [--console <dependency>]` writes a plugin from the template in the package (`template/plugin`, the words `__key__`, `__name__` and `
|
|
463
|
-
- `
|
|
475
|
+
- `console-plugin init <dir> --key <key> [--name <name>] [--console <dependency>] [--package <name>] [--repository <url> [--directory <path>]] [--languages <tags>]` writes a plugin from the template in the package (`template/plugin`, the words `__package__`, `__key__`, `__name__`, `__console__` and `__consoleRange__` replaced in its files and their names; `--console` is the `devDependency` on `@skillcdn/console`, `^<the command's version>` unless said, and the manifest's `console` is the line of the version it names, `>=0.4.3 <0.5.0` for `^0.4.3`, left out where the dependency names no version, as `workspace:*` does not): the manifest, a server module with one collection, one command and one query, the source of a web bundle with the bridge client, one page and one widget, one skill with `SKILLCDN.md`, tests against `@skillcdn/console/plugin/testing` and of the package as a console reads it, and the build with esbuild (`build.mjs`: the server module, the web bundle and its stylesheet). `examples/plugin-hello` in the repository is that result, built, and the check holds the two equal.
|
|
476
|
+
- `init` takes beside the key what a plugin bound for a repository or a registry would otherwise have adapted by hand: `--package <name>`, the package's name (`console-plugin-<key>` unless said; a scoped name, `@<scope>/console-plugin-<key>`, gets `publishConfig.access: "public"`); `--repository <url>` with `--directory <path>` in a repository of several, which fill `package.json`'s `repository`, `homepage` and `bugs` and the manifest's `store.homepage` and `store.repository`; and `--languages en,ko`, the languages of the plugin's words, `en` first, which gives every language map of the manifest and the `translations` of `SKILLCDN.md` and of the skill the other languages as the English words, for the author to translate. `check` warns of a translation left the same as English.
|
|
477
|
+
- `console-plugin check [<dir>]` reads the package as the console would and fails on: an invalid manifest; a reserved or malformed key; a `pluginApi` the command does not know; a `devDependency` on `@skillcdn/console` outside the consoles the manifest's `console` declares; a server module that does not load under the host's hardening, or yields a definition naming a role, a setting, a collection or a page that is not declared; a built-in the host refuses, imported anywhere in the server bundle; a web bundle that is not self-contained (a script, a style or an import from elsewhere; `fetch`, `XMLHttpRequest`, `WebSocket` or `document.cookie` in it); a class without the `pl-<key>-` prefix; skills that `skillcdn check` refuses; a license that is not permissive; a `files` field that leaves out what runs. It is what a store would ask of a plugin. It needs Node.js 24 or newer; it warns, and does not fail, on a private package, a class without the prefix, a capability no definition uses, skills left out, and a `console` range that leaves out the console the command belongs to; it exits `1` with every problem, `0` with a summary.
|
|
464
478
|
- `createTestContext({ collections?, plugin?, caller?, console?, sql?, fetch?, secrets?, plugins?, now?, language? })` from `@skillcdn/console/plugin/testing` is a `ctx` for a plugin's own tests: records in memory, checked against the schema and the indexes as the console checks them, versions, links and files kept; the console answering what the test provided and refusing the rest as `plugin.forbidden`; `emitted` and `logged` to assert on; `all(collection)` for every record; `as(caller)` for the same store as someone else.
|
|
465
479
|
- The skill `skills/building-a-plugin` is the map: what to ask, how to split a feature into commands, queries, decisions, tasks and jobs so that agents work and people decide, records or SQL, running a local console with the plugin linked into `PLUGINS_DIR`, the tests, `check`, publishing or tagging, and handing the install to the deployment as a task. It names this document for every field and bound, and repeats none.
|
|
466
|
-
- Before 1.0 the plugin API moves with the console's line; `pluginApi` is raised when the contract breaks, and the console names the majors it serves; a plugin is rebuilt against the console it runs on,
|
|
480
|
+
- Before 1.0 the plugin API moves with the console's line; `pluginApi` is raised when the contract breaks, and the console names the majors it serves; a plugin is rebuilt against the console it runs on, and names the consoles it runs on in `console`, which carries the patch floor a feature of the console's puts under it (an option's `key`, say, which 0.4.3 brought), where `pluginApi` cannot. The generic routes and the command are in the REST snapshot, so an addition stays an addition.
|
|
467
481
|
|
|
468
482
|
## Environment
|
|
469
483
|
|