@mercury-fw/cli 0.39.0 → 0.41.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @mercury-fw/cli
2
2
 
3
+ ## 0.41.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2755f61: New plugin: ZITADEL through the `zitadel` CLI.
8
+
9
+ - New package `@mercury-fw/plugin-zitadel`. It reads users (by email, username or id), their project roles and identity provider links, organizations and projects, as the person Mercury is talking to, who logs in to ZITADEL through Mercury. Nothing it runs changes ZITADEL.
10
+ - The CLI is pinned at 2.6.0. `mfw credentials setup @mercury-fw/plugin-zitadel` sets up the service user the terminal runs as; with `--user-app` it sets up the Native app people log in through.
11
+ - `mfw create` offers it as `zitadel`.
12
+
13
+ ### Patch Changes
14
+
15
+ - @mercury-fw/core@0.41.0
16
+ - @mercury-fw/utils@0.41.0
17
+
18
+ ## 0.40.0
19
+
20
+ ### Minor Changes
21
+
22
+ - 0739f77: A plugin acts as the person Mercury is talking to, who logs in to the service through Mercury.
23
+
24
+ - Plugin contract version 4: a plugin declares `actsAs: "person" | "mercury"`, and one acting as the person contributes a `login`; its tools get the turn's `person` and `requireLogin` in their context.
25
+ - A person is offered only the plugins acting as the person: their prompt fragments, skills and tools. A plugin acting as Mercury, or declaring nothing, is offered on the terminal only until people can be allowed to make Mercury act as itself; the startup log names it.
26
+ - `createCliTool` adds `--user` with the person's id to every command, staged confirmations included, and when the CLI exits with code 3 (not logged in) returns their login instead. `createCliPersonLogin` builds a plugin's `login` on a CLI's two-step remote login. A failed `runCli` carries `exitCode`.
27
+ - Channel contract version 4: channels get `logins` (`accept` a callback URL, `complete` a login) and `detectLoginRequired`.
28
+ - The HTTP channel, with `HTTP_SURFACE_PUBLIC_URL` set, streams a `login` event with the link to open and takes the person back at `GET /login/callback`, public and protected by the single-use state.
29
+ - `mercury.cliCredentials` can declare `userSetup`, run by `mfw credentials setup <plugin> --user-app`: the app people log in through, set up without logging anyone in.
30
+ - plugin-jira and plugin-bitbucket act as the person, on CLIs 2.3.0: set up their people's app with `--user-app` and register `<HTTP_SURFACE_PUBLIC_URL>/login/callback` on it. Jira's skill now says `currentUser()` is the person.
31
+ - plugin-atlassian-admin acts as Mercury, on CLI 0.2.0, whose `init` asks for the key without echoing it: until permissions exist it's available on the terminal only.
32
+ - A third-party plugin needs `apiVersion: 4` to load, and `actsAs: "person"` with a `login` to be offered to people.
33
+
34
+ ### Patch Changes
35
+
36
+ - Updated dependencies [0739f77]
37
+ - @mercury-fw/core@0.40.0
38
+ - @mercury-fw/utils@0.40.0
39
+
3
40
  ## 0.39.0
4
41
 
5
42
  ### Minor Changes
package/README.md CHANGED
@@ -60,7 +60,7 @@ Then it runs `bun install` in the app and creates a git repository on `main` wit
60
60
  | `--assistant-name <name>` | The assistant's name (default `Mercury`). |
61
61
  | `--role <text>` | Completes "You are <name>, …" (default `an internal assistant`). |
62
62
  | `--channels <ids>` | Comma-separated: `google-chat`, `http`. |
63
- | `--plugins <ids>` | Comma-separated: `jira`, `bitbucket`, `atlassian-admin`. |
63
+ | `--plugins <ids>` | Comma-separated: `jira`, `bitbucket`, `atlassian-admin`, `zitadel`. |
64
64
  | `--auth <id>` | The HTTP channel's auth provider, `oidc` or `static`: required with `http`, refused without it, since the channel doesn't start without one. The wizard asks for it once `http` is chosen. |
65
65
  | `--local-packages <folder>` | Installs the packages packed in `<folder>` (`bun pm pack`) instead of the registry's, as [`mfw local-packages`](#mfw-local-packages-folder--mfw-local-packages---off) does on an existing app: their versions come from the tarballs, so a package that isn't published yet works too, and no newer `mfw` is looked up on the registry. For trying unreleased packages in a new app; the test bed makes its apps this way. |
66
66
  | `--git-remote <url>` | The repository's `origin`, taken as typed. |
@@ -56,11 +56,13 @@ export declare function appCommands(app: App, deps: AppDeps): {
56
56
  * brings its service back up on an empty volume. The volume's real name
57
57
  * comes from the compose file, and a wrong answer deletes nothing. */
58
58
  reset: (target: ResetTarget) => Promise<number>;
59
- /** Runs the plugin's declared setup in a one-off container on the user's
60
- * terminal (without `-T`, compose attaches a TTY whenever stdin is one),
59
+ /** Runs the plugin's declared setup (with `userApp`, of the app people log
60
+ * in through) in a one-off container on the user's terminal (without `-T`, compose attaches a TTY whenever stdin is one),
61
61
  * so the CLI asks what it needs and writes its login straight onto the
62
62
  * credentials volume. */
63
- credentialsSetup: (plugin: string) => Promise<number>;
63
+ credentialsSetup: (plugin: string, { userApp }?: {
64
+ userApp?: boolean;
65
+ }) => Promise<number>;
64
66
  /** Runs the plugin's declared check in a one-off container. */
65
67
  credentialsCheck: (plugin: string) => Promise<number>;
66
68
  /** Runs the plugin's declared logout, of the service identity or of the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mercury-fw/cli",
3
- "version": "0.39.0",
3
+ "version": "0.41.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,19 +41,20 @@
41
41
  "comment:shape": "The Mercury CLI (`mfw`). `mfw create <dir>` writes a new Mercury app from the template. The framework packages move in lockstep with it, so a new app gets them at the CLI's own version; plugins and channels at the registry's latest. The plugin and channel packages are devDependencies only for the catalog test. `main(argv)` is exported for create-mercury-agent.",
42
42
  "dependencies": {
43
43
  "@clack/prompts": "^1.8.1",
44
- "@mercury-fw/core": "0.39.0",
45
- "@mercury-fw/utils": "0.39.0",
44
+ "@mercury-fw/core": "0.41.0",
45
+ "@mercury-fw/utils": "0.41.0",
46
46
  "commander": "^15.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@mercury-fw/channel-google-chat": "0.3.0",
50
- "@mercury-fw/channel-http": "0.4.0",
49
+ "@mercury-fw/channel-google-chat": "0.4.0",
50
+ "@mercury-fw/channel-http": "0.5.0",
51
51
  "@mercury-fw/auth-oidc": "0.1.0",
52
52
  "@mercury-fw/auth-static": "0.1.0",
53
- "@mercury-fw/formatter": "0.39.0",
54
- "@mercury-fw/plugin-atlassian-admin": "0.2.0",
55
- "@mercury-fw/plugin-bitbucket": "0.2.0",
56
- "@mercury-fw/plugin-jira": "0.5.0",
53
+ "@mercury-fw/formatter": "0.41.0",
54
+ "@mercury-fw/plugin-atlassian-admin": "0.3.0",
55
+ "@mercury-fw/plugin-bitbucket": "0.3.0",
56
+ "@mercury-fw/plugin-jira": "0.6.0",
57
+ "@mercury-fw/plugin-zitadel": "0.1.0",
57
58
  "@mercury-fw/typescript-config": "*",
58
59
  "@types/bun": "^1.4.2",
59
60
  "typescript": "^6.0.3"
@@ -128,13 +128,15 @@ export function appCommands(app: App, deps: AppDeps) {
128
128
  }
129
129
  return 0;
130
130
  },
131
- /** Runs the plugin's declared setup in a one-off container on the user's
132
- * terminal (without `-T`, compose attaches a TTY whenever stdin is one),
131
+ /** Runs the plugin's declared setup (with `userApp`, of the app people log
132
+ * in through) in a one-off container on the user's terminal (without `-T`, compose attaches a TTY whenever stdin is one),
133
133
  * so the CLI asks what it needs and writes its login straight onto the
134
134
  * credentials volume. */
135
- credentialsSetup: async (plugin: string) => {
135
+ credentialsSetup: async (plugin: string, { userApp = false }: { userApp?: boolean } = {}) => {
136
136
  const declared = credentialsOf(app, plugin);
137
- const code = await deps.run([...COMPOSE, "run", "--rm", "--no-deps", SERVICE, ...inContainer(declared, declared.setup)], {
137
+ const setup = userApp ? declared.userSetup : declared.setup;
138
+ if (setup === undefined) throw new Error(`${declared.package} declares no setup for an app people log in through: it doesn't act as the person.`);
139
+ const code = await deps.run([...COMPOSE, "run", "--rm", "--no-deps", SERVICE, ...inContainer(declared, setup)], {
138
140
  cwd: app.dir,
139
141
  });
140
142
  if (code === 0 && declared.check !== undefined) deps.print(`Next: mfw credentials check ${declared.package}`);
package/src/catalog.ts CHANGED
@@ -58,6 +58,7 @@ export const CATALOG: CatalogEntry[] = [
58
58
  env: [
59
59
  { name: "HTTP_SURFACE_PORT", comment: "Port of the HTTP surface", value: "4100" },
60
60
  { name: "HTTP_SURFACE_CORS_ORIGIN", comment: "Origin allowed to call the HTTP surface from a browser, if any" },
61
+ { name: "HTTP_SURFACE_PUBLIC_URL", comment: "Address people's browsers reach the HTTP surface at, for logging in to the services plugins act on as them" },
61
62
  ],
62
63
  },
63
64
  {
@@ -114,6 +115,13 @@ export const CATALOG: CatalogEntry[] = [
114
115
  exportName: "atlassianAdminPlugin",
115
116
  env: [],
116
117
  },
118
+ {
119
+ id: "zitadel",
120
+ kind: "tool",
121
+ package: "@mercury-fw/plugin-zitadel",
122
+ exportName: "zitadelPlugin",
123
+ env: [],
124
+ },
117
125
  ];
118
126
 
119
127
  /** The catalog entry of `kind` with `id`, or undefined when there is none. */
package/src/program.ts CHANGED
@@ -236,10 +236,13 @@ Examples:
236
236
  .command("setup")
237
237
  .summary("sets up a CLI's login in the app's container")
238
238
  .description(
239
- "Runs the setup the plugin declares for its CLI's service identity (the identity Mercury acts as), in a one-off container on your terminal: the CLI asks for what it needs, and its login lands on the credentials volume. People log in on their own later, through Mercury.",
239
+ "Runs the setup the plugin declares for its CLI's service identity (the identity Mercury acts as), in a one-off container on your terminal: the CLI asks for what it needs, and its login lands on the credentials volume. People log in on their own later, through Mercury: for a plugin acting as the person, --user-app sets up the app they log in through.",
240
240
  )
241
241
  .argument("<plugin>", "the plugin's package (@mercury-fw/plugin-jira) or its CLI's folder as declared (jira-cli)")
242
- .action(async (plugin: string) => inApp((app) => app.credentialsSetup(plugin))());
242
+ .option("--user-app", "set up instead the app people log in through, for a plugin acting as the person (logs nobody in)")
243
+ .action(async (plugin: string, opts: { userApp?: boolean }) =>
244
+ inApp((app) => app.credentialsSetup(plugin, opts.userApp ? { userApp: true } : {}))(),
245
+ );
243
246
  credentials
244
247
  .command("check")
245
248
  .summary("checks a CLI's login")