@ory/amp 0.13.9 → 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
@@ -21,12 +21,14 @@ Run one command. It installs the plugin and walks you through connecting:
21
21
  npx -y -p @ory/amp ory-amp install
22
22
  ```
23
23
 
24
- You'll be asked how you want to connect — **press Enter for the default**:
24
+ It opens a guided setup **in your browser** where you pick how to connect — the default takes just a click:
25
25
 
26
26
  - **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.
27
27
  - **Local** — run a complete Ory on your laptop with Docker. No account, no signup, no keys. Great for trying it out.
28
28
  - **Audit-only** — skip Ory entirely and just log what Amp does.
29
29
 
30
+ > No browser available (CI, SSH, headless)? The same walkthrough runs right in your terminal instead — or force it with `--no-web`.
31
+
30
32
  That's it. Confirm everything landed with:
31
33
 
32
34
  ```bash
@@ -52,6 +54,7 @@ If Ory is ever slow or unreachable, the plugin gets out of the way and lets Amp
52
54
  Everything the plugin does is observable out of the box — no configuration required:
53
55
 
54
56
  - **Status at a glance.** `npx -y -p @ory/amp ory-amp status` shows what's configured, who's signed in, how many built-in tools your permissions cover, and the most recent tool-call activity.
57
+ - **Live dashboard.** `npx -y -p @ory/amp ory-amp 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.
55
58
  - **Live traces.** Every tool call is recorded as an OpenTelemetry-style span. Watch them stream as the agent works:
56
59
 
57
60
  ```bash
@@ -69,7 +72,7 @@ When the watch-mode logs look right, turn on blocking with one command (setup al
69
72
  npx -y -p @ory/amp ory-amp permissions enforce
70
73
  ```
71
74
 
72
- Now a denied tool is actually blocked and Amp 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.
75
+ Now a denied tool is actually blocked and Amp 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.
73
76
 
74
77
  <details>
75
78
  <summary>How the plugin plugs into Amp</summary>
@@ -100,22 +103,22 @@ The guided setup covers most people. For scripted or CI setups, or to point at a
100
103
  ```bash
101
104
  npx -y -p @ory/amp ory-amp configure \
102
105
  --project-url https://<slug>.projects.oryapis.com \
103
- --oauth2-client-id <sign-in client id> \
104
- --user-login
106
+ --oauth2-client-id <sign-in client id>
105
107
  ```
106
108
 
107
- Amp'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 public client registered with the four loopback callback URLs `http://127.0.0.1:47823..47826/callback`); the guided setup makes it for you. Pass `--api-key ory_pat_...` only to override Amp's auto-created identity with a static token. 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`.
109
+ Amp'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 public client registered with the four loopback callback URLs `http://127.0.0.1:47823..47826/callback`); the guided setup makes it for you. Pass `--api-key ory_pat_...` only to override Amp's auto-created identity with a static token. For logging-only with no checks, use `--audit-only`. The interactive user login runs every session (always on, non-blocking) and only needs `ORY_OAUTH2_CLIENT_ID` to complete the browser flow. The matching env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, and `ORY_AGENT_API_KEY`.
108
110
 
109
111
  With nothing configured, the plugin still loads and runs in **pass-through mode**: skills and logging work, but no checks run and nothing is blocked. Perfectly fine if you only want the app-building features.
110
112
 
111
113
  ## Commands
112
114
 
113
115
  ```
114
- ory-amp install | uninstall Install/remove; --reconfigure re-runs setup, --no-configure skips it
116
+ ory-amp install | uninstall Install/remove; --reconfigure re-runs setup, --no-web forces the terminal wizard, --no-configure skips it
115
117
  ory-amp status Show configuration, identities, permission coverage, and recent activity
118
+ ory-amp dashboard Open the live browser dashboard (status + service health + Change stack)
116
119
  ory-amp watch Tail the live trace stream (OTel spans)
117
120
  ory-amp permissions <cmd> status | bootstrap | observe (watch) | enforce (block)
118
- ory-amp configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --user-login, --audit-only)
121
+ ory-amp configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --audit-only)
119
122
  ory-amp agent <status|unregister> Manage Amp's own auto-created identity
120
123
  ```
121
124
 
package/dist/cli/main.js CHANGED
@@ -100,6 +100,12 @@ function main() {
100
100
  case "watch":
101
101
  (0, argus_1.runWatchCommand)("amp", args);
102
102
  break;
103
+ case "dashboard":
104
+ (0, argus_1.runDashboardCommand)("ory-amp", "amp", args).then((code) => process.exit(code), (err) => {
105
+ console.error(err.message ?? err);
106
+ process.exit(1);
107
+ });
108
+ break;
103
109
  case "version":
104
110
  case "--version":
105
111
  case "-v":
@@ -183,6 +189,7 @@ Commands:
183
189
  (status, bootstrap, observe, enforce)
184
190
  setup [--project-dir <path>] Write config directly (fallback)
185
191
  status [--project-dir <path>] Show plugin configuration and status
192
+ dashboard Open the Ory Agent dashboard (system health + configuration)
186
193
  watch [trace-file] Tail the trace stream (OTel spans) live
187
194
  version Show version and the ory-agent-plugins build commit
188
195
  local <cmd> Manage local Ory dev environment
package/dist/plugin.d.ts CHANGED
@@ -6,8 +6,8 @@
6
6
  * Each handler receives the event payload and a `PluginEventContext`. We
7
7
  * subscribe to:
8
8
  *
9
- * session.start → run the user gate (advisory, allowBlock:false), the
10
- * agent gate, and write the user→agent delegation tuple.
9
+ * session.start → run the user gate, the agent gate, and write the
10
+ * user→agent delegation tuple.
11
11
  * tool.result → record a `tool.complete` audit span.
12
12
  *
13
13
  * The BLOCKING permission decision deliberately does NOT live here. Amp's
@@ -18,9 +18,9 @@
18
18
  * observational. The delegate runs as its own process and decides by exit
19
19
  * code; this module only authenticates and traces.
20
20
  *
21
- * Because Amp's `session.start` handler has no return-value channel for
22
- * blocking, the user login runs in advisory mode (allowBlock:false), like
23
- * the OpenCode / OpenClaw factory plugins.
21
+ * The user login runs every session and never blocks it emits the
22
+ * user.auth audit span, refreshes tokens, and may prompt when interactive.
23
+ * Enforcement is governed solely by permissionMode at tool-call time.
24
24
  */
25
25
  import { OryAgentClient, ensureUserAuthenticated, ensureAgentIdentity } from "@ory/argus";
26
26
  import type { AmpPlugin } from "./types.js";
package/dist/plugin.js CHANGED
@@ -7,8 +7,8 @@
7
7
  * Each handler receives the event payload and a `PluginEventContext`. We
8
8
  * subscribe to:
9
9
  *
10
- * session.start → run the user gate (advisory, allowBlock:false), the
11
- * agent gate, and write the user→agent delegation tuple.
10
+ * session.start → run the user gate, the agent gate, and write the
11
+ * user→agent delegation tuple.
12
12
  * tool.result → record a `tool.complete` audit span.
13
13
  *
14
14
  * The BLOCKING permission decision deliberately does NOT live here. Amp's
@@ -19,9 +19,9 @@
19
19
  * observational. The delegate runs as its own process and decides by exit
20
20
  * code; this module only authenticates and traces.
21
21
  *
22
- * Because Amp's `session.start` handler has no return-value channel for
23
- * blocking, the user login runs in advisory mode (allowBlock:false), like
24
- * the OpenCode / OpenClaw factory plugins.
22
+ * The user login runs every session and never blocks it emits the
23
+ * user.auth audit span, refreshes tokens, and may prompt when interactive.
24
+ * Enforcement is governed solely by permissionMode at tool-call time.
25
25
  */
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
27
  exports.createOryPlugin = createOryPlugin;
@@ -55,17 +55,15 @@ function createSessionStartHandler(client, deps) {
55
55
  client.tracer.record("session.start", "ok", {
56
56
  attributes: sessionId ? { sessionId } : {},
57
57
  });
58
- // Run the user login. Amp's session.start has no block primitive, so
59
- // allowBlock is false — the flow emits the user.auth audit span,
60
- // refreshes tokens, and may prompt when interactive, but never
61
- // prevents the session from starting. When ORY_USER_LOGIN is unset it
62
- // is a no-op (mode === "disabled") and we fall through to legacy
63
- // logging.
58
+ // Run the user login. It runs every session and never blocks the
59
+ // flow emits the user.auth audit span, refreshes tokens, and may
60
+ // prompt when interactive, but never prevents the session from
61
+ // starting. Enforcement is governed solely by permissionMode at
62
+ // tool-call time.
64
63
  const userGate = deps.userLogin ?? argus_1.ensureUserAuthenticated;
65
- const decision = await userGate(client, {
64
+ await userGate(client, {
66
65
  binName: "ory-amp",
67
66
  harness: "amp",
68
- allowBlock: false,
69
67
  });
70
68
  // Resolve the agent identity (machine credentials). Never blocks;
71
69
  // attaches the agent's bearer token to outgoing Ory API calls.
@@ -75,76 +73,8 @@ function createSessionStartHandler(client, deps) {
75
73
  // tuple. Written at most once per install + fail-open: audit-trail data
76
74
  // only.
77
75
  await (0, argus_1.writeUserDelegatesAgent)(client);
78
- if (decision.mode !== "disabled") {
79
- return;
80
- }
81
- const resolved = (0, argus_1.resolveConfig)();
82
- if (resolved.auditOnly) {
83
- client.logger.info("config.audit_only", {
84
- message: "Audit-only mode enabled. Auth and permission checks are disabled.",
85
- });
86
- return;
87
- }
88
- if (!resolved.projectUrl) {
89
- client.logger.warn("config.not_configured", {
90
- message: "Ory plugin is not configured. Auth and permission checks are disabled. " +
91
- "Run 'npx ory-amp configure' to connect to an Ory project.",
92
- });
93
- return;
94
- }
95
- const sessionToken = process.env.ORY_SESSION_TOKEN;
96
- const oauth2Token = process.env.ORY_OAUTH2_TOKEN;
97
- if (sessionToken) {
98
- await verifySessionToken(client, sessionToken);
99
- return;
100
- }
101
- if (oauth2Token) {
102
- await verifyOAuth2Token(client, oauth2Token);
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
- });
109
76
  };
110
77
  }
111
- async function verifySessionToken(client, token) {
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
- client.logger.warn("session.verify_failed", {
122
- code: isOryError(err) ? err.code : "unknown",
123
- message: err instanceof Error ? err.message : String(err),
124
- });
125
- }
126
- }
127
- async function verifyOAuth2Token(client, token) {
128
- try {
129
- const tokenInfo = await client.introspectToken(token);
130
- if (!tokenInfo.active) {
131
- client.logger.warn("oauth2.token_inactive", {
132
- message: "Ory OAuth2 token is not active. Obtain a new token to enable auth checks.",
133
- });
134
- return;
135
- }
136
- client.logger.info("oauth2.session_authenticated", {
137
- clientId: tokenInfo.clientId,
138
- subject: tokenInfo.subject,
139
- });
140
- }
141
- catch (err) {
142
- client.logger.warn("oauth2.introspect_failed", {
143
- code: isOryError(err) ? err.code : "unknown",
144
- message: err instanceof Error ? err.message : String(err),
145
- });
146
- }
147
- }
148
78
  // ─── tool.result ───────────────────────────────────────────────────
149
79
  function createToolResultHandler(client) {
150
80
  return async (event, _ctx) => {
@@ -172,10 +102,3 @@ function createToolResultHandler(client) {
172
102
  });
173
103
  };
174
104
  }
175
- // ─── Helpers ───────────────────────────────────────────────────────
176
- function isOryError(err) {
177
- return (typeof err === "object" &&
178
- err !== null &&
179
- "code" in err &&
180
- "message" in err);
181
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/amp",
3
- "version": "0.13.9",
3
+ "version": "0.14.0",
4
4
  "description": "Ory plugin for Amp (Sourcegraph's coding agent): a permission delegate that authorizes every tool call plus an in-process plugin for session auth and audit tracing",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ory.com",
@@ -68,7 +68,7 @@
68
68
  ],
69
69
  "dependencies": {
70
70
  "reo-census": "^1.2.8",
71
- "@ory/argus": "0.13.9"
71
+ "@ory/argus": "0.14.0"
72
72
  },
73
73
  "devDependencies": {
74
74
  "typescript": "^6.0.2",