@ory/goose 0.13.8 → 0.14.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/README.md CHANGED
@@ -23,12 +23,14 @@ Run one command. It installs the plugin and walks you through connecting:
23
23
  npx -y -p @ory/goose ory-goose install
24
24
  ```
25
25
 
26
- The installer drops a self-contained plugin at `<project>/.agents/plugins/ory/`, where Goose finds it on its own at startup — no `goose configure` step and nothing else in your Goose config gets touched. Then it asks how you want to connect — **press Enter for the default**:
26
+ The installer drops a self-contained plugin at `<project>/.agents/plugins/ory/`, where Goose finds it on its own at startup — no `goose configure` step and nothing else in your Goose config gets touched. Then it opens a guided setup **in your browser** where you pick how to connect — the default takes just a click:
27
27
 
28
28
  - **Ory Network** *(default)* — sign in, or create a free account, in your browser. The project, keys, permissions, and login are all set up for you. Nothing to configure by hand.
29
29
  - **Local** — run a complete Ory on your laptop with Docker. No account, no signup, no keys. Great for trying it out.
30
30
  - **Audit-only** — skip Ory entirely and just log what Goose does.
31
31
 
32
+ > No browser available (CI, SSH, headless)? The same walkthrough runs right in your terminal instead — or force it with `--no-web`.
33
+
32
34
  That's it. Confirm everything landed with:
33
35
 
34
36
  ```bash
@@ -54,6 +56,7 @@ Under the hood, Goose runs the plugin as a small program for each thing it does,
54
56
  Everything the plugin does is observable out of the box — no configuration required:
55
57
 
56
58
  - **Status at a glance.** `npx -y -p @ory/goose ory-goose status` shows what's configured, who's signed in, how many built-in tools your permissions cover, and the most recent tool-call activity.
59
+ - **Live dashboard.** `npx -y -p @ory/goose ory-goose dashboard` opens the same picture in your browser — configuration, identities, permission coverage, Ory service health, and the latest tool-call activity, all refreshing live. From there you can flip **enforcement** on or off, toggle **user login**, and use **Change stack** to reconnect to a different Ory — no CLI required.
57
60
  - **Live traces.** Every tool call is recorded as an OpenTelemetry-style span. Watch them stream as the agent works:
58
61
 
59
62
  ```bash
@@ -71,7 +74,7 @@ When the watch-mode logs look right, turn on blocking with one command (setup al
71
74
  npx -y -p @ory/goose ory-goose permissions enforce
72
75
  ```
73
76
 
74
- Now a denied tool is actually blocked and Goose shows why. Go back to watch mode anytime with `permissions observe`. Use `permissions status` to see what's covered and `permissions bootstrap` to (re-)grant the built-in tools.
77
+ Now a denied tool is actually blocked and Goose shows why. Go back to watch mode anytime with `permissions observe`. Prefer clicking? The dashboard has the same **Enforce** switch — flip it on, or back to watch mode, without touching the CLI. Use `permissions status` to see what's covered and `permissions bootstrap` to (re-)grant the built-in tools.
75
78
 
76
79
  ## Also: add login to your own app
77
80
 
@@ -86,11 +89,10 @@ The guided setup covers most people. For scripted or CI setups, or to point at a
86
89
  ```bash
87
90
  npx -y -p @ory/goose ory-goose configure \
88
91
  --project-url https://<slug>.projects.oryapis.com \
89
- --oauth2-client-id <sign-in client id> \
90
- --user-login
92
+ --oauth2-client-id <sign-in client id>
91
93
  ```
92
94
 
93
- Goose's own identity registers itself automatically on first run — nothing to create. The `--oauth2-client-id` is the one piece browser sign-in needs (the guided setup makes it for you). Persist the login toggle with `--user-login` / `--no-user-login`, or set it per-session with `ORY_USER_LOGIN=true`. For logging-only with no checks, use `--audit-only`. The matching env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, `ORY_USER_LOGIN`, and `ORY_AGENT_API_KEY`.
95
+ Goose's own identity registers itself automatically on first run — nothing to create. The `--oauth2-client-id` is the one piece browser sign-in needs (the guided setup makes it for you). The interactive user login runs every session (always on, non-blocking) and only needs `ORY_OAUTH2_CLIENT_ID` to complete the browser flow. For logging-only with no checks, use `--audit-only`. The matching env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, and `ORY_AGENT_API_KEY`.
94
96
 
95
97
  <details>
96
98
  <summary>Create the sign-in client by hand</summary>
@@ -99,7 +101,7 @@ The guided setup normally does this. To do it yourself, create a **public** OAut
99
101
 
100
102
  ```bash
101
103
  ory create oauth2-client --project <project-id> \
102
- --name "ory-agent-plugin" \
104
+ --name "Ory Agent Security · user login (PKCE)" \
103
105
  --grant-type authorization_code,refresh_token \
104
106
  --response-type code \
105
107
  --scope openid,offline_access \
@@ -119,11 +121,12 @@ With nothing configured, the plugin still loads and runs in **pass-through mode*
119
121
  ## Commands
120
122
 
121
123
  ```
122
- ory-goose install | uninstall Install/remove; --reconfigure re-runs setup, --no-configure skips it, --global installs everywhere
124
+ ory-goose install | uninstall Install/remove; --reconfigure re-runs setup, --no-web forces the terminal wizard, --no-configure skips it, --global installs everywhere
123
125
  ory-goose status Show configuration, identities, permission coverage, registration, recent activity
126
+ ory-goose dashboard Open the live browser dashboard (status + service health + Change stack)
124
127
  ory-goose watch Tail the live trace stream (OTel spans)
125
128
  ory-goose permissions <cmd> status | bootstrap | observe (watch) | enforce (block)
126
- ory-goose configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --user-login, --audit-only)
129
+ ory-goose configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --audit-only)
127
130
  ory-goose agent <status|unregister> Manage Goose's own auto-created identity
128
131
  ```
129
132
 
package/dist/cli/main.js CHANGED
@@ -106,6 +106,12 @@ function main() {
106
106
  case "watch":
107
107
  (0, argus_1.runWatchCommand)("goose", args);
108
108
  break;
109
+ case "dashboard":
110
+ (0, argus_1.runDashboardCommand)("ory-goose", "goose", args).then((code) => process.exit(code), (err) => {
111
+ console.error(err.message ?? err);
112
+ process.exit(1);
113
+ });
114
+ break;
109
115
  case "version":
110
116
  case "--version":
111
117
  case "-v":
@@ -170,6 +176,7 @@ Commands:
170
176
  permissions <cmd> Manage permission mode and tool permissions (status, bootstrap, observe, enforce)
171
177
  setup [--project-dir] Write the plugin tree directly (advanced)
172
178
  status Show plugin status and configuration
179
+ dashboard Open the Ory Agent dashboard (system health + configuration)
173
180
  watch [trace-file] Tail the trace stream (OTel spans) live
174
181
  version Show version and the ory-agent-plugins build commit
175
182
  local <cmd> Manage local Ory dev environment (up, down, status, seed, ...)
package/dist/cli/setup.js CHANGED
@@ -109,7 +109,7 @@ function renderManifest(version) {
109
109
  * regex `matcher`/`pattern`) is verified against goose v1.39.0.
110
110
  */
111
111
  function renderHooks(version) {
112
- const command = `npx -y -p ${PACKAGE_NAME}@${version} ${HOOK_BIN}`;
112
+ const command = (0, argus_1.pinHookToLocalRegistry)(`npx -y -p ${PACKAGE_NAME}@${version} ${HOOK_BIN}`);
113
113
  const entry = [{ type: "command", command }];
114
114
  return {
115
115
  hooks: {
package/dist/handlers.js CHANGED
@@ -58,96 +58,21 @@ async function handleSessionStart(input, client, deps) {
58
58
  });
59
59
  client.tracer.record("session.start", "ok", {});
60
60
  const userGate = deps.userLogin ?? argus_1.ensureUserAuthenticated;
61
- const decision = await userGate(client, {
61
+ // The user login runs every session and never blocks; tool-call
62
+ // enforcement is governed solely by permissionMode.
63
+ await userGate(client, {
62
64
  binName: "ory-goose",
63
65
  harness: "goose",
64
- // Goose's PreToolUse carries exit code 2; SessionStart is a subprocess
65
- // hook too, so a declined login can hard-block the session.
66
- allowBlock: true,
67
66
  });
68
67
  // Resolve the agent identity (machine credentials). Never blocks;
69
68
  // attaches the agent's bearer token to outgoing Ory API calls.
70
69
  const agentGate = deps.agentGate ?? argus_1.ensureAgentIdentity;
71
70
  await agentGate(client, { projectUrl: (0, argus_1.resolveConfig)().projectUrl, harness: "goose" });
72
- // User → agent delegation tuple (best-effort, audit-trail only).
73
- await recordUserDelegatesAgent(client);
74
- if (!decision.proceed) {
75
- return { action: "block", message: decision.reason };
76
- }
77
- if (decision.mode !== "disabled") {
78
- return {};
79
- }
80
- const resolved = (0, argus_1.resolveConfig)();
81
- if (resolved.auditOnly) {
82
- client.logger.info("config.audit_only", {
83
- message: "Audit-only mode enabled. Auth and permission checks are disabled.",
84
- });
85
- return {};
86
- }
87
- if (!resolved.projectUrl) {
88
- client.logger.warn("config.not_configured", {
89
- message: "Ory plugin is not configured. Auth and permission checks are disabled. " +
90
- "Run 'npx ory-goose configure' to connect to an Ory project.",
91
- });
92
- return {};
93
- }
94
- // Legacy pre-supplied token verification (backward compat).
95
- const sessionToken = process.env.ORY_SESSION_TOKEN;
96
- const oauth2Token = process.env.ORY_OAUTH2_TOKEN;
97
- if (sessionToken) {
98
- await verifySessionToken(sessionToken, client);
99
- return {};
100
- }
101
- if (oauth2Token) {
102
- await verifyOAuth2Token(oauth2Token, client);
103
- return {};
104
- }
105
- client.logger.warn("session.no_credentials", {
106
- message: "Neither ORY_SESSION_TOKEN nor ORY_OAUTH2_TOKEN is set. " +
107
- "Skipping authentication.",
108
- });
71
+ // User → agent delegation tuple (best-effort, audit-trail only). Written
72
+ // at most once per install.
73
+ await (0, argus_1.writeUserDelegatesAgent)(client);
109
74
  return {};
110
75
  }
111
- async function verifySessionToken(token, client) {
112
- try {
113
- const session = await client.verifySession(token);
114
- if (!session.active) {
115
- client.logger.warn("session.inactive", {
116
- message: "Ory session is not active. Re-authenticate to enable auth checks.",
117
- });
118
- }
119
- }
120
- catch (err) {
121
- const oryErr = err;
122
- client.logger.warn("session.verify_failed", {
123
- code: oryErr.code,
124
- message: oryErr.message,
125
- });
126
- }
127
- }
128
- async function verifyOAuth2Token(token, client) {
129
- try {
130
- const tokenInfo = await client.introspectToken(token);
131
- if (!tokenInfo.active) {
132
- client.logger.warn("oauth2.token_inactive", {
133
- message: "Ory OAuth2 token is not active. Obtain a new token to enable auth checks.",
134
- });
135
- return;
136
- }
137
- client.logger.info("oauth2.session_authenticated", {
138
- clientId: tokenInfo.clientId,
139
- subject: tokenInfo.subject,
140
- scope: tokenInfo.scope,
141
- });
142
- }
143
- catch (err) {
144
- const oryErr = err;
145
- client.logger.warn("oauth2.introspect_failed", {
146
- code: oryErr.code,
147
- message: oryErr.message,
148
- });
149
- }
150
- }
151
76
  // ─── PreToolUse ────────────────────────────────────────────────────
152
77
  async function handlePreToolUse(input, client) {
153
78
  const toolName = input.tool_name ?? "unknown";
@@ -279,40 +204,6 @@ async function handleTraceOnly(input, client) {
279
204
  function resolveNamespace() {
280
205
  return process.env.ORY_PERMISSION_NAMESPACE ?? "AgentTools";
281
206
  }
282
- /**
283
- * Write the user→agent delegation tuple. Idempotent and fail-open:
284
- * requires both principal subjects to be populated; any error (including
285
- * unconfigured projectUrl, which manifests as a network_error) is logged
286
- * and swallowed. The actual permission enforcement is unchanged — this
287
- * tuple is purely audit-trail data.
288
- */
289
- async function recordUserDelegatesAgent(client) {
290
- const user = client.userPrincipal.subject;
291
- const agent = client.agentPrincipal.subject;
292
- if (!user || !agent) {
293
- client.logger.debug("delegation.skip", {
294
- reason: "missing principal",
295
- hasUser: !!user,
296
- hasAgent: !!agent,
297
- });
298
- return;
299
- }
300
- try {
301
- await client.createRelationship({
302
- namespace: resolveNamespace(),
303
- object: `agent:${agent}`,
304
- relation: "delegate",
305
- subjectId: `user:${user}`,
306
- }, { spanAttributes: { delegation: "user-to-agent" } });
307
- }
308
- catch (err) {
309
- const oryErr = err;
310
- client.logger.warn("delegation.user_to_agent.failed", {
311
- code: oryErr.code,
312
- message: oryErr.message,
313
- });
314
- }
315
- }
316
207
  function handlePermissionError(oryErr, toolName, client) {
317
208
  if (oryErr.code === "network_error") {
318
209
  client.logger.warn("permission.network_error", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/goose",
3
- "version": "0.13.8",
3
+ "version": "0.14.0",
4
4
  "description": "Ory plugin for Goose (Block's open-source agent CLI): scaffolding skills, a local Ory instance, and authentication, authorization, and audit for every tool call",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ory.com",
@@ -67,7 +67,7 @@
67
67
  ],
68
68
  "dependencies": {
69
69
  "reo-census": "^1.2.8",
70
- "@ory/argus": "0.13.8"
70
+ "@ory/argus": "0.14.0"
71
71
  },
72
72
  "devDependencies": {
73
73
  "typescript": "^6.0.2",