@ory/argus 0.14.0 → 1.0.1
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 +31 -46
- package/assets/commands/temporal-up.md +1 -1
- package/assets/skills/auth-setup/SKILL.md +1 -1
- package/assets/skills/local-dev/SKILL.md +17 -7
- package/assets/skills/ory-build-agent/SKILL.md +39 -91
- package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -17
- package/assets/skills/ory-temporal-worker/SKILL.md +31 -33
- package/assets/skills/permissions-onboarding/SKILL.md +131 -104
- package/dist/adapters.d.ts +88 -32
- package/dist/adapters.js +443 -164
- package/dist/agent-auth.d.ts +226 -67
- package/dist/agent-auth.js +951 -205
- package/dist/auth-store.d.ts +37 -2
- package/dist/auth-store.js +37 -3
- package/dist/auth.d.ts +33 -4
- package/dist/auth.js +163 -20
- package/dist/bash-parser.d.ts +98 -0
- package/dist/bash-parser.js +396 -0
- package/dist/branding.d.ts +77 -16
- package/dist/branding.js +93 -23
- package/dist/build-info.json +4 -4
- package/dist/cli-invocation.d.ts +1 -1
- package/dist/cli-invocation.js +2 -1
- package/dist/cli.d.ts +20 -29
- package/dist/cli.js +271 -239
- package/dist/client.d.ts +175 -138
- package/dist/client.js +672 -391
- package/dist/config.d.ts +217 -54
- package/dist/config.js +461 -42
- package/dist/context.d.ts +10 -0
- package/dist/context.js +21 -0
- package/dist/contract-suite.d.ts +3 -5
- package/dist/contract-suite.js +75 -47
- package/dist/denial.d.ts +36 -3
- package/dist/denial.js +79 -10
- package/dist/event-reporter.d.ts +77 -0
- package/dist/event-reporter.js +776 -0
- package/dist/external-registrations-main.d.ts +10 -0
- package/dist/external-registrations-main.js +38 -0
- package/dist/external-registrations.d.ts +79 -0
- package/dist/external-registrations.js +188 -0
- package/dist/help-cli.d.ts +39 -0
- package/dist/help-cli.js +55 -0
- package/dist/hook-timeout.d.ts +64 -0
- package/dist/hook-timeout.js +88 -0
- package/dist/index.d.ts +28 -23
- package/dist/index.js +173 -58
- package/dist/lifecycle.d.ts +3 -3
- package/dist/lifecycle.js +38 -6
- package/dist/local/cli.js +11 -6
- package/dist/local/configs.d.ts +74 -18
- package/dist/local/configs.js +291 -84
- package/dist/local/health.js +7 -7
- package/dist/local/index.d.ts +2 -2
- package/dist/local/index.js +24 -10
- package/dist/local/manager.d.ts +20 -1
- package/dist/local/manager.js +159 -36
- package/dist/local/ports.d.ts +158 -0
- package/dist/local/ports.js +443 -0
- package/dist/local/seed.d.ts +13 -5
- package/dist/local/seed.js +62 -38
- package/dist/logger.d.ts +54 -25
- package/dist/logger.js +329 -63
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +10 -5
- package/dist/mirror-bootstrap.d.ts +48 -0
- package/dist/mirror-bootstrap.js +254 -0
- package/dist/opl.d.ts +289 -0
- package/dist/opl.js +446 -0
- package/dist/permission-mode.d.ts +87 -0
- package/dist/permission-mode.js +307 -0
- package/dist/permissions-cli.d.ts +13 -49
- package/dist/permissions-cli.js +154 -348
- package/dist/permissions.d.ts +148 -38
- package/dist/permissions.js +591 -45
- package/dist/post-install.d.ts +33 -0
- package/dist/post-install.js +127 -0
- package/dist/read-credential.d.ts +65 -0
- package/dist/read-credential.js +86 -0
- package/dist/registry/cli.js +5 -2
- package/dist/registry/config.d.ts +0 -17
- package/dist/registry/config.js +0 -23
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.js +2 -2
- package/dist/registry/manager.d.ts +4 -21
- package/dist/registry/manager.js +21 -37
- package/dist/runtime-credential.d.ts +140 -0
- package/dist/runtime-credential.js +572 -0
- package/dist/runtime.d.ts +413 -0
- package/dist/runtime.js +825 -0
- package/dist/setup.d.ts +23 -47
- package/dist/setup.js +59 -116
- package/dist/skills.js +0 -7
- package/dist/status-cli.d.ts +27 -11
- package/dist/status-cli.js +121 -115
- package/dist/status-data.d.ts +116 -17
- package/dist/status-data.js +121 -38
- package/dist/subject.d.ts +126 -20
- package/dist/subject.js +215 -30
- package/dist/testing.d.ts +74 -38
- package/dist/testing.js +185 -68
- package/dist/tool-catalog.d.ts +53 -11
- package/dist/tool-catalog.js +164 -13
- package/dist/tool-metadata.d.ts +7 -6
- package/dist/tool-metadata.js +6 -5
- package/dist/types.d.ts +11 -1
- package/dist/uninstall.d.ts +71 -34
- package/dist/uninstall.js +217 -85
- package/dist/user-login.d.ts +9 -10
- package/dist/user-login.js +56 -75
- package/dist/watch-cli.d.ts +6 -0
- package/dist/watch-cli.js +217 -0
- package/package.json +4 -27
- package/assets/commands/dashboard.md +0 -34
- package/dist/dashboard-cli.d.ts +0 -8
- package/dist/dashboard-cli.js +0 -70
- package/dist/dev.d.ts +0 -103
- package/dist/dev.js +0 -583
- package/dist/interactive-setup.d.ts +0 -286
- package/dist/interactive-setup.js +0 -1734
- package/dist/local/jaeger-main.d.ts +0 -13
- package/dist/local/jaeger-main.js +0 -85
- package/dist/local/jaeger.d.ts +0 -50
- package/dist/local/jaeger.js +0 -162
- package/dist/otel/exporter.d.ts +0 -17
- package/dist/otel/exporter.js +0 -12
- package/dist/otel/index.d.ts +0 -2
- package/dist/otel/index.js +0 -8
- package/dist/otel/otlp.d.ts +0 -103
- package/dist/otel/otlp.js +0 -385
- package/dist/project-api-key.d.ts +0 -69
- package/dist/project-api-key.js +0 -147
- package/dist/setup-actions.d.ts +0 -232
- package/dist/setup-actions.js +0 -507
- package/dist/tracer.d.ts +0 -190
- package/dist/tracer.js +0 -481
- package/dist/watch-sandbox.d.ts +0 -9
- package/dist/watch-sandbox.js +0 -81
- package/dist/web/api.d.ts +0 -33
- package/dist/web/api.js +0 -294
- package/dist/web/launch.d.ts +0 -11
- package/dist/web/launch.js +0 -96
- package/dist/web/server.d.ts +0 -20
- package/dist/web/server.js +0 -233
- package/dist/web/types.d.ts +0 -65
- package/dist/web/types.js +0 -2
- package/dist/webapp/assets/index-Wucl4SZs.css +0 -1
- package/dist/webapp/assets/index-m-GtEdq0.js +0 -49
- package/dist/webapp/favicon.ico +0 -0
- package/dist/webapp/index.html +0 -15
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ory-temporal-worker
|
|
3
|
-
description: Scaffold a [Temporal](https://temporal.io) TypeScript worker where every Activity execution is gated by Ory — the user is authenticated, the worker's agent identity is resolved via DCR, each Activity invocation runs an Ory Permission check, and the full lifecycle emits
|
|
3
|
+
description: Scaffold a [Temporal](https://temporal.io) TypeScript worker where every Activity execution is gated by Ory — the user is authenticated, the worker's agent identity is resolved via DCR, each Activity invocation runs an Ory Permission check, and the full lifecycle emits structured activity events. Use when the user asks to "add Ory to my Temporal worker", "wire Ory permissions into Temporal activities", "create a Temporal worker with Ory auth", "build a Temporal TypeScript project with the Ory agent client", or any close variant. The skill scaffolds the project in the user's repo following <https://docs.temporal.io/develop/typescript/set-up-your-local-typescript> — it does not run the worker.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Ory-authed Temporal TypeScript worker
|
|
@@ -9,7 +9,7 @@ You are helping the user scaffold a [Temporal](https://temporal.io) TypeScript
|
|
|
9
9
|
worker where every Activity execution is gated by Ory: the user is
|
|
10
10
|
authenticated, the worker's agent identity is resolved via OAuth2 Dynamic Client
|
|
11
11
|
Registration, each Activity invocation runs an Ory Permission check, and the
|
|
12
|
-
full lifecycle emits
|
|
12
|
+
full lifecycle emits structured activity events. **Workflows stay deterministic** — only
|
|
13
13
|
Activities call out to Ory.
|
|
14
14
|
|
|
15
15
|
This skill carries the workflow. You generate the files in the user's repo; the
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
} from "@ory/argus";
|
|
71
71
|
|
|
72
72
|
// One client per worker process. `harness` is a label that shows up on
|
|
73
|
-
// every
|
|
73
|
+
// every activity event so worker-originated audit lives in its own namespace
|
|
74
74
|
// alongside the CLI plugins.
|
|
75
75
|
const ory = OryAgentClient.fromEnv("temporal");
|
|
76
76
|
|
|
@@ -84,7 +84,7 @@ function bootstrap(): Promise<void> {
|
|
|
84
84
|
binName: "temporal-worker",
|
|
85
85
|
harness: "temporal",
|
|
86
86
|
// The user gate runs every invocation and never blocks: it refreshes
|
|
87
|
-
// tokens and emits the audit
|
|
87
|
+
// tokens and emits the audit event, but the worker proceeds even if the
|
|
88
88
|
// user is unauthenticated. Enforcement happens at the per-Activity
|
|
89
89
|
// permission check (permissionMode).
|
|
90
90
|
});
|
|
@@ -102,13 +102,13 @@ async function gate(toolName: string, userSubject: string): Promise<void> {
|
|
|
102
102
|
const decision = await checkAndDecide(
|
|
103
103
|
ory,
|
|
104
104
|
{
|
|
105
|
-
namespace: process.env.ORY_PERMISSION_NAMESPACE ?? "
|
|
105
|
+
namespace: process.env.ORY_PERMISSION_NAMESPACE ?? "AgentTool",
|
|
106
106
|
object: toolName,
|
|
107
107
|
relation: "use",
|
|
108
108
|
...subject,
|
|
109
109
|
},
|
|
110
110
|
{
|
|
111
|
-
|
|
111
|
+
activityAttributes: {
|
|
112
112
|
toolName,
|
|
113
113
|
workflowId: Context.current().info.workflowExecution.workflowId,
|
|
114
114
|
activityId: Context.current().info.activityId,
|
|
@@ -147,9 +147,9 @@ Key choices:
|
|
|
147
147
|
identity, but always proceeds. Enforcement is at the permission check, which
|
|
148
148
|
throws on deny — Temporal will mark the Activity as failed and surface the
|
|
149
149
|
error via the Workflow result or retry policy.
|
|
150
|
-
- **`harness: "temporal"`.** Distinguishes worker-originated
|
|
151
|
-
|
|
152
|
-
- **
|
|
150
|
+
- **`harness: "temporal"`.** Distinguishes worker-originated events in the
|
|
151
|
+
unified activity log.
|
|
152
|
+
- **Activity attributes carry the Workflow + Activity IDs.** This is how operators
|
|
153
153
|
correlate Ory denials back to Temporal executions in the Web UI.
|
|
154
154
|
|
|
155
155
|
## Step 4 — Pass the user subject through the Workflow
|
|
@@ -215,7 +215,7 @@ cd temporal-worker
|
|
|
215
215
|
export ORY_PROJECT_URL=http://localhost:4000
|
|
216
216
|
export ORY_AUTH_GATE=1
|
|
217
217
|
export ORY_AGENT_DEBUG=true
|
|
218
|
-
export
|
|
218
|
+
export ORY_AGENT_LOG_FILE=$PWD/ory-agent-debug.log
|
|
219
219
|
npm run start # boots the worker, polls task queue
|
|
220
220
|
```
|
|
221
221
|
|
|
@@ -226,49 +226,47 @@ cd temporal-worker
|
|
|
226
226
|
npm run workflow
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
-
Tail the
|
|
229
|
+
Tail the activity log to confirm the gates fired:
|
|
230
230
|
|
|
231
231
|
```bash
|
|
232
|
-
tail -f ory-
|
|
232
|
+
tail -f ory-agent-debug.log | jq .
|
|
233
233
|
```
|
|
234
234
|
|
|
235
235
|
You should see:
|
|
236
236
|
|
|
237
|
-
- exactly one `user.auth`
|
|
237
|
+
- exactly one `user.auth` activity event (the worker's first Activity triggered
|
|
238
238
|
`bootstrap()`),
|
|
239
|
-
- exactly one `agent.auth`
|
|
240
|
-
- one `tool.invoke` (allow) or `tool.block` (deny)
|
|
239
|
+
- exactly one `agent.auth` activity event,
|
|
240
|
+
- one `tool.invoke` (allow) or `tool.block` (deny) event **per Activity
|
|
241
241
|
execution**.
|
|
242
242
|
|
|
243
|
-
The Workflow itself produces no Ory
|
|
243
|
+
The Workflow itself produces no Ory activity — only its Activities do.
|
|
244
244
|
|
|
245
245
|
## Step 6 — Promotion from observe to enforce
|
|
246
246
|
|
|
247
247
|
The worker starts in `observe` mode by default: denies pass through but each is
|
|
248
|
-
recorded as a `permission.observe_deny`
|
|
249
|
-
the deny set is what they expect,
|
|
248
|
+
recorded as a `permission.observe_deny` activity event. Once the user has confirmed
|
|
249
|
+
the deny set is what they expect, an admin promotes the posture to `enforce` in
|
|
250
|
+
the Ory Console (Agent Security). It is a permission on the project, read on
|
|
251
|
+
every session, so the worker picks it up on its next run with no redeploy.
|
|
250
252
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
On a fresh Ory project, run the permissions bootstrap once before flipping the
|
|
256
|
-
switch so the `use` tuples for each Activity name (`send_email`, …) exist —
|
|
257
|
-
see {{REF_PERMISSIONS_ONBOARDING}}.
|
|
253
|
+
On a hosted Ory project, grant `use` on each Activity name (`send_email`, …) in
|
|
254
|
+
the Ory Console (Agent Security) before promoting the posture there — otherwise
|
|
255
|
+
enforcement blocks every Activity. See {{REF_PERMISSIONS_ONBOARDING}}.
|
|
258
256
|
|
|
259
|
-
To exercise the deny path locally,
|
|
260
|
-
|
|
261
|
-
|
|
257
|
+
To exercise the deny path locally, kick the Workflow with an Activity name the
|
|
258
|
+
local stack never granted, and watch it fail with the `Ory denied use of …`
|
|
259
|
+
error in the Temporal Web UI.
|
|
262
260
|
|
|
263
261
|
## Step 7 — Beyond the dev server
|
|
264
262
|
|
|
265
263
|
This skill stops at the local dev server. For production:
|
|
266
264
|
|
|
267
|
-
- Pin a static agent identity with `
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
-
|
|
271
|
-
|
|
265
|
+
- Pin a static agent identity with `ORY_AGENT_CLIENT_ID +
|
|
266
|
+
ORY_AGENT_CLIENT_SECRET` (client_credentials) so the worker doesn't
|
|
267
|
+
re-register on every cold start.
|
|
268
|
+
- Set retention and access controls for the worker's unified activity log.
|
|
269
|
+
Ory Agent Security owns service telemetry; the worker does not export traces.
|
|
272
270
|
- Use Temporal Cloud or a self-hosted Temporal cluster instead of
|
|
273
271
|
`temporal server start-dev`; the worker code does not change.
|
|
274
272
|
|
|
@@ -1,32 +1,57 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ory-permissions-onboarding
|
|
3
|
-
description: Onboard a fresh install onto Ory Permissions for AI agent tool calls. Use when the user has just installed the Ory plugin and wants
|
|
3
|
+
description: Onboard a fresh install onto Ory Permissions for AI agent tool calls. Use when the user has just installed the Ory plugin and wants per-tool authorization enforced without first getting blocked by missing permissions. Covers connecting the plugin, reading coverage in observe mode, and what has to happen in the Ory Console (grants, blocks, enforce posture).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Onboard onto Ory Permissions for Agent Tool Calls
|
|
7
7
|
|
|
8
8
|
You are helping a user move a freshly-installed Ory agent plugin from
|
|
9
|
-
"permissions are
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
"disconnected" to "permissions are enforcing", without the common
|
|
10
|
+
first-run failure mode of getting every tool call blocked because the
|
|
11
|
+
project has no grants yet.
|
|
12
|
+
|
|
13
|
+
**The plugin only reads permissions. It never writes them.** Everything
|
|
14
|
+
that provisions the project — the permission model, per-tool grants,
|
|
15
|
+
explicit blocks, and the observe/enforce posture — is done in the **Ory
|
|
16
|
+
Console** (Agent Security) by someone with access to the project. That
|
|
17
|
+
split is deliberate: it means installing and connecting a plugin needs
|
|
18
|
+
nothing but project connection details and a public OAuth2 client id, with no
|
|
19
|
+
workspace privilege and no project API key.
|
|
20
|
+
|
|
21
|
+
Two things govern behavior:
|
|
22
|
+
|
|
23
|
+
- **Whether Agent Security is connected** — it runs when a project URL,
|
|
24
|
+
canonical Agent Security origin, and public OAuth2 client id resolve. Existing
|
|
25
|
+
configurations fall back to the project URL when the canonical origin is
|
|
26
|
+
unset. Not connected means no login and no permission checks, with
|
|
27
|
+
tool calls recorded locally. Skills, commands, the local dev stack, and
|
|
28
|
+
the MCP server work either way — they don't need a project at all.
|
|
29
|
+
- **`permissionMode`** — `observe` or `enforce`, **read from the Ory
|
|
30
|
+
project** on every session, and only meaningful once connected.
|
|
31
|
+
`observe` (the default) runs every check, records denials, and lets the
|
|
32
|
+
tool proceed. `enforce` blocks on deny. There is no local override — an
|
|
33
|
+
admin sets it in the Console.
|
|
34
|
+
|
|
35
|
+
The journey: **install → connect → observe → grant in the Console →
|
|
36
|
+
enforce in the Console.**
|
|
37
|
+
|
|
38
|
+
## Step 1: Connect the plugin to the project
|
|
39
|
+
|
|
40
|
+
A fresh install has the developer-experience half working and Agent
|
|
41
|
+
Security not connected. Copy the connection details shown in the Ory Console
|
|
42
|
+
under **Agent Security**:
|
|
13
43
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
auth, no permission checks). This is for users who want only audit
|
|
18
|
-
logging of tool invocations. Not what onboarding is about.
|
|
19
|
-
- **`permissionMode`** — the dial this skill is about. `observe` (the
|
|
20
|
-
default) runs every permission check, logs denials, but allows the
|
|
21
|
-
tool to proceed. `enforce` blocks on deny. Mode is read from
|
|
22
|
-
`ORY_PERMISSION_MODE` first, then the shared config file, then
|
|
23
|
-
defaults to `observe`.
|
|
24
|
-
|
|
25
|
-
The journey: **install → observe → bootstrap → enforce.**
|
|
44
|
+
```sh
|
|
45
|
+
{{NPX}} configure --project-url <URL> --agent-security-url <URL>
|
|
46
|
+
```
|
|
26
47
|
|
|
27
|
-
|
|
48
|
+
- **project URL** — the project's SDK URL (`https://<slug>.projects.oryapis.com`).
|
|
49
|
+
- **Agent Security URL** — the canonical broker origin (`https://agents.console.ory.com` in production).
|
|
50
|
+
- **OAuth2 client id** — the project's public login client, provisioned
|
|
51
|
+
in the Console. The per-session user login needs it to complete its
|
|
52
|
+
PKCE browser flow.
|
|
28
53
|
|
|
29
|
-
|
|
54
|
+
Then confirm what the plugin resolved:
|
|
30
55
|
|
|
31
56
|
```sh
|
|
32
57
|
{{NPX}} status
|
|
@@ -35,133 +60,135 @@ Verify the plugin is wired up and pointing at the right Ory project:
|
|
|
35
60
|
What you want to see:
|
|
36
61
|
|
|
37
62
|
- **Project URL**: a real Ory URL or your local dev gateway (not "NOT SET").
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
|
|
41
|
-
If any of those are wrong, fix them before continuing:
|
|
63
|
+
- **OAuth2 Client**: the project's public login client (not "NOT SET").
|
|
64
|
+
- **Agent Security**: connected. If it says "not connected", it names the
|
|
65
|
+
unresolved connection value.
|
|
42
66
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
`--oauth2-client-id` is the public OAuth2 client registered in your Ory project (needed for the per-session user login to complete its PKCE browser flow; see the *Register the user OAuth2 client* section of the plugin README).
|
|
67
|
+
If the user doesn't have those values, they need them from whoever
|
|
68
|
+
administers the project. Don't try to create the client from here — the
|
|
69
|
+
plugin has no privilege to, by design.
|
|
48
70
|
|
|
49
71
|
## Step 2: Look at the current permission posture
|
|
50
72
|
|
|
51
73
|
```sh
|
|
52
|
-
{{NPX}} permissions
|
|
74
|
+
{{NPX}} permissions
|
|
53
75
|
```
|
|
54
76
|
|
|
55
77
|
This prints:
|
|
56
78
|
|
|
57
|
-
- The
|
|
58
|
-
|
|
59
|
-
- The **subject**
|
|
79
|
+
- The live **permission mode** (`observe` or `enforce`) and whether it
|
|
80
|
+
came from the project, a cached value, or the default.
|
|
81
|
+
- The **subject** — the user identity permissions are checked against.
|
|
60
82
|
- For each tool in this harness's built-in catalog, **allowed / denied /
|
|
61
|
-
errored
|
|
62
|
-
|
|
83
|
+
blocked / errored**, from a real check against the project right now.
|
|
84
|
+
- A one-line coverage summary for decomposed shell command words.
|
|
63
85
|
|
|
64
|
-
On a
|
|
65
|
-
**denied** —
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
blocked once enforce mode is turned on.
|
|
86
|
+
On a freshly-connected project you will usually see every tool reported
|
|
87
|
+
as **denied** — no grants exist for this user yet. In observe mode that
|
|
88
|
+
blocks nobody: tool calls run through, and you are seeing what *would*
|
|
89
|
+
be blocked under enforce.
|
|
69
90
|
|
|
70
|
-
If
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
non-blocking.
|
|
91
|
+
If status prints `Mode: enforce` while tools are denied, tool calls
|
|
92
|
+
**are** being blocked right now. The fix is in the Console (grant the
|
|
93
|
+
tools, or move the project back to observe) — not from the CLI.
|
|
74
94
|
|
|
75
|
-
## Step 3:
|
|
95
|
+
## Step 3: Run a real session in observe mode
|
|
76
96
|
|
|
77
|
-
|
|
97
|
+
Observe mode is the discovery phase. Use the harness normally, then look
|
|
98
|
+
at what was recorded:
|
|
78
99
|
|
|
79
100
|
```sh
|
|
80
|
-
{{NPX}}
|
|
101
|
+
{{NPX}} status # summary + recent activity
|
|
102
|
+
{{NPX}} watch # live event, decision, and error view
|
|
81
103
|
```
|
|
82
104
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
in the harness's known catalog. MCP server tools are *not* covered —
|
|
89
|
-
they are discovered dynamically per session, so they need tuples added
|
|
90
|
-
out-of-band as they come into scope.
|
|
91
|
-
|
|
92
|
-
### When bootstrap can't write tuples
|
|
105
|
+
Launch the harness with `ORY_AGENT_DEBUG=true` to include verbose diagnostics in
|
|
106
|
+
the watched log and stderr. Denials appear as `permission.observe_deny` activity events (and
|
|
107
|
+
`permission.block_observed` for an explicit block), with the tool name
|
|
108
|
+
and the subject. That list is exactly what has to be granted before
|
|
109
|
+
enforce is safe.
|
|
93
110
|
|
|
94
|
-
|
|
111
|
+
## Step 4: Grant the tools in the Ory Console
|
|
95
112
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
no `ORY_USER_SUBJECT_ID`), the command refuses. Run the harness once
|
|
99
|
-
(the user login runs every session) to cache a user token, or set
|
|
100
|
-
`ORY_USER_SUBJECT_ID=<id>` to target a known subject.
|
|
101
|
-
2. **Credentials lack write scope on the permission namespace.** The
|
|
102
|
-
command prints the full tuple list so you can apply them manually
|
|
103
|
-
via `keto relation-tuples create`, the Ory Console's *Add
|
|
104
|
-
relationship* dialog, or `curl` against Keto's write API. Hand the
|
|
105
|
-
list to whoever holds write credentials.
|
|
106
|
-
|
|
107
|
-
### Add tuples for non-default tools
|
|
108
|
-
|
|
109
|
-
If the harness has tools beyond the built-in catalog (MCP servers,
|
|
110
|
-
custom commands), grant them by writing tuples directly. Use the same
|
|
111
|
-
shape:
|
|
113
|
+
In the Ory Console → **Agent Security**, grant the subject `use` on the
|
|
114
|
+
tools it needs. The grant shape the runtime checks is:
|
|
112
115
|
|
|
113
116
|
```
|
|
114
|
-
namespace:
|
|
115
|
-
object: <tool name>
|
|
117
|
+
namespace: AgentTool (or whatever ORY_PERMISSION_NAMESPACE is set to)
|
|
118
|
+
object: <tool name> (e.g. Read, Bash, WebFetch)
|
|
116
119
|
relation: use
|
|
117
|
-
subject:
|
|
120
|
+
subject: User:<id> (a SubjectSet — namespace `User`, object the user id)
|
|
118
121
|
```
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
Notes worth passing on to the user:
|
|
121
124
|
|
|
122
|
-
|
|
125
|
+
- The subject is a **SubjectSet** (`User:<id>`), which is what the
|
|
126
|
+
Console's *Add relationship* dialog emits and exactly what the runtime
|
|
127
|
+
check uses. A bare subject id will not match.
|
|
128
|
+
- Granting a **group** and putting users in it scales better than
|
|
129
|
+
per-user grants; the check follows subject-set expansion.
|
|
130
|
+
- **Shell command words** are authorized separately in the `ShellTool`
|
|
131
|
+
namespace (`ShellTool:curl#use`, …) because a denied surface is
|
|
132
|
+
otherwise reachable through `bash -c "curl …"`.
|
|
133
|
+
- **MCP server tools** are discovered dynamically per session, so they
|
|
134
|
+
are not in the built-in catalog and need granting as they come into
|
|
135
|
+
scope.
|
|
123
136
|
|
|
124
|
-
|
|
125
|
-
`allowed`, flip the dial:
|
|
137
|
+
Re-run `{{NPX}} permissions` afterwards to confirm coverage.
|
|
126
138
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
139
|
+
## Step 5: Promote to enforce in the Console
|
|
140
|
+
|
|
141
|
+
Once the tools the user actually needs report `allowed`, an admin flips
|
|
142
|
+
the posture in the Console (Agent Security). The mode is a permission on
|
|
143
|
+
the project, so it can be set **project-wide** — covering principals
|
|
144
|
+
that don't exist yet — or **per principal** as an exception.
|
|
130
145
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
can always be flipped back:
|
|
146
|
+
Every session reads the live mode, so the change takes effect without
|
|
147
|
+
reinstalling or reconfiguring anything. Confirm it landed:
|
|
134
148
|
|
|
135
149
|
```sh
|
|
136
|
-
{{NPX}} permissions
|
|
150
|
+
{{NPX}} permissions
|
|
137
151
|
```
|
|
138
152
|
|
|
139
|
-
|
|
140
|
-
runs that want enforce regardless of what's persisted, or for one-off
|
|
141
|
-
debugging sessions where you want observe without rewriting config.
|
|
142
|
-
|
|
143
|
-
## Step 5: Verify a real session
|
|
153
|
+
## Step 6: Verify a real session under enforce
|
|
144
154
|
|
|
145
155
|
Start a normal agent session and confirm:
|
|
146
156
|
|
|
147
157
|
- **Allowed tools** invoke without complaint.
|
|
148
|
-
- **Denied tools**
|
|
149
|
-
|
|
150
|
-
- The
|
|
151
|
-
`tool.block`
|
|
158
|
+
- **Denied tools** are blocked with a clear "Ory: permission denied"
|
|
159
|
+
message naming the tool (or the shell command word).
|
|
160
|
+
- The activity log shows `permission.check` events per tool call and
|
|
161
|
+
`tool.block` events for denials.
|
|
162
|
+
|
|
163
|
+
If a tool is unexpectedly blocked, run `{{NPX}} permissions` to
|
|
164
|
+
see whether it is `denied` (no grant) or `blocked` (an explicit
|
|
165
|
+
deny-override), then fix it in the Console and re-test.
|
|
166
|
+
|
|
167
|
+
## Explicit blocks (deny-override)
|
|
168
|
+
|
|
169
|
+
Granting is additive. To express the opposite — a subject is **blocked**
|
|
170
|
+
from a tool, beating any grant, including one inherited through a group —
|
|
171
|
+
an admin writes a `blockedSubjects` relation in the Console. Ory evaluates it
|
|
172
|
+
natively (the `use` permit is "granted AND not blocked"), so it holds
|
|
173
|
+
no matter how the grant was reached.
|
|
152
174
|
|
|
153
|
-
|
|
154
|
-
|
|
175
|
+
A block behaves like any other deny: under **observe** it is recorded (a
|
|
176
|
+
`permission.block_observed` activity event) but the tool still runs; under
|
|
177
|
+
**enforce** it blocks. `permissions` marks blocked tools so they
|
|
178
|
+
are distinguishable from a plain missing grant at a glance.
|
|
155
179
|
|
|
156
|
-
## Reference
|
|
180
|
+
## Reference
|
|
157
181
|
|
|
158
182
|
| Command | Effect |
|
|
159
183
|
|---|---|
|
|
160
|
-
| `{{NPX}}
|
|
161
|
-
| `{{NPX}}
|
|
162
|
-
| `{{NPX}} permissions
|
|
163
|
-
| `{{NPX}}
|
|
164
|
-
|
|
184
|
+
| `{{NPX}} configure --project-url <URL> --agent-security-url <URL>` | Connect the plugin to the canonical Agent Security broker. |
|
|
185
|
+
| `{{NPX}} configure --disconnect` | Turn sign-in and permission checks back off. Skills, commands, the local stack, and activity logging are unaffected. |
|
|
186
|
+
| `{{NPX}} permissions` | Print the live mode + per-tool allowed/denied/blocked breakdown. Read-only. |
|
|
187
|
+
| `{{NPX}} status` | Configuration, identities, permission coverage, recent activity. |
|
|
188
|
+
|
|
189
|
+
Done in the **Ory Console** (Agent Security), not from the CLI: applying
|
|
190
|
+
the permission model, granting `use` on tools, writing explicit blocks,
|
|
191
|
+
and setting the observe/enforce posture.
|
|
165
192
|
|
|
166
193
|
For deeper background on the authentication side of the flow (which
|
|
167
194
|
identity is the subject, how the user gate resolves it), see
|