@ory/argus 0.13.9 → 1.0.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 +31 -45
- 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 +43 -97
- package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -18
- package/assets/skills/ory-temporal-worker/SKILL.md +38 -42
- package/assets/skills/permissions-onboarding/SKILL.md +131 -104
- package/dist/adapters.d.ts +93 -30
- package/dist/adapters.js +464 -136
- package/dist/agent-auth.d.ts +258 -68
- package/dist/agent-auth.js +998 -202
- package/dist/auth-store.d.ts +37 -2
- package/dist/auth-store.js +37 -3
- package/dist/auth.d.ts +40 -4
- package/dist/auth.js +247 -19
- package/dist/bash-parser.d.ts +98 -0
- package/dist/bash-parser.js +396 -0
- package/dist/branding.d.ts +128 -0
- package/dist/branding.js +151 -0
- 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 -278
- package/dist/client.d.ts +175 -138
- package/dist/client.js +672 -391
- package/dist/config.d.ts +249 -57
- package/dist/config.js +486 -62
- package/dist/context.d.ts +10 -0
- package/dist/context.js +21 -0
- package/dist/contract-suite.d.ts +8 -8
- package/dist/contract-suite.js +88 -69
- 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 +31 -19
- package/dist/index.js +182 -31
- 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.d.ts +14 -0
- package/dist/local/health.js +50 -4
- 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 +160 -39
- package/dist/local/ports.d.ts +158 -0
- package/dist/local/ports.js +443 -0
- package/dist/local/seed.d.ts +22 -25
- package/dist/local/seed.js +88 -56
- 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 +83 -55
- package/dist/runtime-credential.d.ts +140 -0
- package/dist/runtime-credential.js +572 -0
- package/dist/runtime.d.ts +408 -0
- package/dist/runtime.js +748 -0
- package/dist/setup.d.ts +23 -28
- package/dist/setup.js +57 -84
- package/dist/status-cli.d.ts +29 -13
- package/dist/status-cli.js +124 -144
- package/dist/status-data.d.ts +195 -0
- package/dist/status-data.js +333 -0
- package/dist/status-system.d.ts +24 -0
- package/dist/status-system.js +56 -0
- 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 +74 -19
- package/dist/uninstall.js +224 -49
- package/dist/user-login.d.ts +22 -16
- package/dist/user-login.js +67 -96
- package/dist/watch-cli.d.ts +6 -0
- package/dist/watch-cli.js +217 -0
- package/package.json +3 -11
- package/dist/dev.d.ts +0 -103
- package/dist/dev.js +0 -584
- package/dist/interactive-setup.d.ts +0 -165
- package/dist/interactive-setup.js +0 -1546
- 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/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
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The bootstrap committed to the public install-surface mirrors.
|
|
4
|
+
*
|
|
5
|
+
* Three harnesses install from a git repo rather than from npm — Claude Code
|
|
6
|
+
* (plugin marketplace), Gemini CLI (`gemini extensions install <url>`) and
|
|
7
|
+
* Codex (`codex plugin marketplace add <url>`) — so those repos carry a
|
|
8
|
+
* checked-in `hooks.json` / manifest. A machine-specific shim path cannot go
|
|
9
|
+
* into a file a teammate will clone, and an `npx` command must not go back onto
|
|
10
|
+
* the tool-call path, so those surfaces instead reference a **bootstrap** that
|
|
11
|
+
* ships inside the plugin tree, addressed through the harness's own path
|
|
12
|
+
* variable (verified per harness — see `docs/distribution.md`).
|
|
13
|
+
*
|
|
14
|
+
* The bootstrap is deliberately **dependency-free**: the mirror repos have no
|
|
15
|
+
* `node_modules`, so it uses `node:` builtins only. It does three things:
|
|
16
|
+
*
|
|
17
|
+
* 1. Read the runtime manifest this machine's `install` wrote and `require`
|
|
18
|
+
* the wired entry. That is the steady state, and it costs one file read.
|
|
19
|
+
* 2. On a **session-start** event with nothing wired, complete the install
|
|
20
|
+
* once by shelling out to `npx <package> install`. This is what keeps
|
|
21
|
+
* `claude plugin install …` a working one-liner: the marketplace install
|
|
22
|
+
* is the install, and the runtime it needs is materialized on first use —
|
|
23
|
+
* never per hook invocation.
|
|
24
|
+
* 3. Fail **open** in every other unresolved case: print what to run, emit
|
|
25
|
+
* the harness's pass-through response, exit 0. A tool-call event never
|
|
26
|
+
* triggers a materialize, because a `PreToolUse` hook has seconds to
|
|
27
|
+
* answer and a harness that treats an unanswered gate as a block would
|
|
28
|
+
* otherwise block the tool while npm ran.
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.renderMirrorBootstrap = renderMirrorBootstrap;
|
|
32
|
+
const DEFAULT_SESSION_START_EVENTS = [
|
|
33
|
+
"SessionStart",
|
|
34
|
+
"session_start",
|
|
35
|
+
"sessionStart",
|
|
36
|
+
"TaskStart",
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Everything both kinds need: locating the data dir the same way
|
|
40
|
+
* `getDataDir()` does, and reading the wiring `install` recorded.
|
|
41
|
+
*/
|
|
42
|
+
function prelude(opts) {
|
|
43
|
+
return `const fs = require("node:fs");
|
|
44
|
+
const os = require("node:os");
|
|
45
|
+
const path = require("node:path");
|
|
46
|
+
|
|
47
|
+
const HARNESS = ${JSON.stringify(opts.harness)};
|
|
48
|
+
const INSTALL_COMMAND = ${JSON.stringify(opts.installCommand)};
|
|
49
|
+
|
|
50
|
+
/** Mirror of \`getDataDir()\` in @ory/argus — keep the two in step. */
|
|
51
|
+
function dataDir() {
|
|
52
|
+
const xdg = (process.env.XDG_CONFIG_HOME || "").trim();
|
|
53
|
+
if (xdg) return path.join(xdg, "ory-agent-plugins");
|
|
54
|
+
if (process.platform === "win32") {
|
|
55
|
+
const appData = (process.env.APPDATA || "").trim();
|
|
56
|
+
if (appData) return path.join(appData, "ory-agent-plugins");
|
|
57
|
+
}
|
|
58
|
+
return path.join(os.homedir(), ".config", "ory-agent-plugins");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The entry this bootstrap should load, or undefined when nothing is wired. */
|
|
62
|
+
function wiredEntry() {
|
|
63
|
+
try {
|
|
64
|
+
const manifest = JSON.parse(
|
|
65
|
+
fs.readFileSync(path.join(dataDir(), "runtime", "manifest.json"), "utf-8")
|
|
66
|
+
);
|
|
67
|
+
const wiring = (manifest.harnesses || {})[HARNESS] || {};
|
|
68
|
+
const entry = wiring[${JSON.stringify(opts.entryKey)}];
|
|
69
|
+
return entry && fs.existsSync(entry) ? entry : undefined;
|
|
70
|
+
} catch {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The hook bootstrap: read the payload, load the runtime, and — only at session
|
|
77
|
+
* start — install it first if it isn't there. Every unresolved path fails open.
|
|
78
|
+
*/
|
|
79
|
+
function hookBody(opts) {
|
|
80
|
+
return `const PACKAGE_NAME = ${JSON.stringify(opts.packageName)};
|
|
81
|
+
const BIN_NAME = ${JSON.stringify(opts.binName)};
|
|
82
|
+
const SESSION_START_EVENTS = ${JSON.stringify(opts.sessionStartEvents)};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Complete the install once. Only ever called for a session-start event, where
|
|
86
|
+
* there is time for it and nothing is waiting on a permission verdict.
|
|
87
|
+
*/
|
|
88
|
+
function materializeOnce() {
|
|
89
|
+
const { spawnSync } = require("node:child_process");
|
|
90
|
+
process.stderr.write(
|
|
91
|
+
"[ory-agent] first run: installing the Ory plugin runtime (" +
|
|
92
|
+
INSTALL_COMMAND +
|
|
93
|
+
")\\n"
|
|
94
|
+
);
|
|
95
|
+
const result = spawnSync(
|
|
96
|
+
"npx",
|
|
97
|
+
["-y", "-p", PACKAGE_NAME, BIN_NAME, "install"],
|
|
98
|
+
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
99
|
+
);
|
|
100
|
+
if (result.status !== 0) {
|
|
101
|
+
process.stderr.write(
|
|
102
|
+
"[ory-agent] runtime install failed. Run it yourself: " +
|
|
103
|
+
INSTALL_COMMAND +
|
|
104
|
+
"\\n" +
|
|
105
|
+
(result.stderr || "").trim() +
|
|
106
|
+
"\\n"
|
|
107
|
+
);
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function isSessionStart(payload) {
|
|
114
|
+
if (!payload) return false;
|
|
115
|
+
for (const key of ["hook_event_name", "hookName", "event", "eventName"]) {
|
|
116
|
+
if (SESSION_START_EVENTS.indexOf(String(payload[key] || "")) !== -1) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Fail open: say what to run, answer harmlessly, exit 0. */
|
|
124
|
+
function failOpen(reason) {
|
|
125
|
+
process.stderr.write(
|
|
126
|
+
"[ory-agent] " +
|
|
127
|
+
reason +
|
|
128
|
+
"\\n[ory-agent] tools are NOT being checked. Run: " +
|
|
129
|
+
INSTALL_COMMAND +
|
|
130
|
+
"\\n"
|
|
131
|
+
);
|
|
132
|
+
${opts.fallbackStdout
|
|
133
|
+
? ` process.stdout.write(${JSON.stringify(opts.fallbackStdout)});\n`
|
|
134
|
+
: ""} process.exit(0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Read stdin before deciding: whether a missing runtime may be installed
|
|
138
|
+
// depends on which event this is, and the payload carries the event name. The
|
|
139
|
+
// runtime's own hook entry reads stdin itself, so buffer and replay it.
|
|
140
|
+
//
|
|
141
|
+
// Buffers, not strings: every hook entry concatenates its chunks with
|
|
142
|
+
// \`Buffer.concat\`, which throws on a string chunk. Replaying byte-for-byte also
|
|
143
|
+
// keeps any non-ASCII payload intact.
|
|
144
|
+
const chunks = [];
|
|
145
|
+
process.stdin.on("data", (chunk) => {
|
|
146
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
147
|
+
});
|
|
148
|
+
process.stdin.on("end", () => {
|
|
149
|
+
const rawBuffer = Buffer.concat(chunks);
|
|
150
|
+
let entry = wiredEntry();
|
|
151
|
+
|
|
152
|
+
if (!entry) {
|
|
153
|
+
let payload;
|
|
154
|
+
try {
|
|
155
|
+
payload = JSON.parse(rawBuffer.toString("utf-8"));
|
|
156
|
+
} catch {
|
|
157
|
+
payload = undefined;
|
|
158
|
+
}
|
|
159
|
+
// A tool event must never wait on npm: answer now, install at session start.
|
|
160
|
+
if (!isSessionStart(payload)) {
|
|
161
|
+
failOpen("no Ory plugin runtime is installed yet");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (!materializeOnce()) {
|
|
165
|
+
failOpen("no Ory plugin runtime is installed");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
entry = wiredEntry();
|
|
169
|
+
if (!entry) {
|
|
170
|
+
failOpen("the runtime install reported success but wired nothing");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const { Readable } = require("node:stream");
|
|
176
|
+
Object.defineProperty(process, "stdin", {
|
|
177
|
+
value: Readable.from([rawBuffer]),
|
|
178
|
+
configurable: true,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
require(entry);
|
|
183
|
+
} catch (err) {
|
|
184
|
+
failOpen(
|
|
185
|
+
"plugin runtime at " +
|
|
186
|
+
entry +
|
|
187
|
+
" could not be loaded: " +
|
|
188
|
+
((err && err.message) || String(err))
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
});`;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The MCP bootstrap. Deliberately the opposite of the hook's fail-open: an MCP
|
|
195
|
+
* server gates nothing, so a silent no-op server is harder to diagnose than a
|
|
196
|
+
* loud exit. It also never installs anything — that belongs to session start,
|
|
197
|
+
* where a hook can afford to wait.
|
|
198
|
+
*/
|
|
199
|
+
function mcpBody() {
|
|
200
|
+
return `const entry = wiredEntry();
|
|
201
|
+
if (!entry) {
|
|
202
|
+
process.stderr.write(
|
|
203
|
+
"[ory-agent] no Ory MCP server runtime is installed. Run: " +
|
|
204
|
+
INSTALL_COMMAND +
|
|
205
|
+
"\\n"
|
|
206
|
+
);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
require(entry);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
process.stderr.write(
|
|
213
|
+
"[ory-agent] Ory MCP server runtime at " +
|
|
214
|
+
entry +
|
|
215
|
+
" could not be loaded: " +
|
|
216
|
+
((err && err.message) || String(err)) +
|
|
217
|
+
"\\n"
|
|
218
|
+
);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}`;
|
|
221
|
+
}
|
|
222
|
+
/** Render the bootstrap script for one entry kind. */
|
|
223
|
+
function renderMirrorBootstrap(kind, opts) {
|
|
224
|
+
const installCommand = `npx -y -p ${opts.packageName} ${opts.binName} install`;
|
|
225
|
+
const head = `#!/usr/bin/env node
|
|
226
|
+
/*
|
|
227
|
+
* Ory ${kind === "hook" ? "hook" : "MCP server"} bootstrap for ${opts.harness}.
|
|
228
|
+
* Generated from @ory/argus — do not edit by hand.
|
|
229
|
+
*
|
|
230
|
+
* Loads the Ory plugin runtime that \`${installCommand}\` resolved on this
|
|
231
|
+
* machine. Dependency-free on purpose: this file ships in a git install surface
|
|
232
|
+
* that has no node_modules.
|
|
233
|
+
*/
|
|
234
|
+
"use strict";
|
|
235
|
+
|
|
236
|
+
`;
|
|
237
|
+
const body = kind === "hook"
|
|
238
|
+
? hookBody({
|
|
239
|
+
packageName: opts.packageName,
|
|
240
|
+
binName: opts.binName,
|
|
241
|
+
sessionStartEvents: opts.sessionStartEvents ?? DEFAULT_SESSION_START_EVENTS,
|
|
242
|
+
fallbackStdout: opts.fallbackStdout,
|
|
243
|
+
})
|
|
244
|
+
: mcpBody();
|
|
245
|
+
return (head +
|
|
246
|
+
prelude({
|
|
247
|
+
harness: opts.harness,
|
|
248
|
+
entryKey: kind === "hook" ? "hookEntry" : "mcpEntry",
|
|
249
|
+
installCommand,
|
|
250
|
+
}) +
|
|
251
|
+
"\n\n" +
|
|
252
|
+
body +
|
|
253
|
+
"\n");
|
|
254
|
+
}
|
package/dist/opl.d.ts
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ory Permission Language (OPL) schema for the Agent Security permission model.
|
|
3
|
+
*
|
|
4
|
+
* Argus relies on more than relation-tuple *existence*: a subject may be granted
|
|
5
|
+
* a tool and separately **blocked** from it, and the block must win. Keto
|
|
6
|
+
* permission is otherwise purely existence-based (no path ⇒ no access, any path
|
|
7
|
+
* ⇒ access), so the deny-override is modeled natively in OPL as a permit:
|
|
8
|
+
*
|
|
9
|
+
* use = users.includes(subject) && !blockedSubjects.includes(subject)
|
|
10
|
+
*
|
|
11
|
+
* Keto evaluates the permit in a single check, so a `blockedSubjects` relation
|
|
12
|
+
* beats a `users` grant no matter how the grant was reached (direct subject or
|
|
13
|
+
* subject-set expansion). Argus always checks the **`use` permit** (see
|
|
14
|
+
* `resolveCheckRelation`), so this model must be applied to the project for
|
|
15
|
+
* checks to resolve; with nothing blocked, `use` resolves identically to a bare
|
|
16
|
+
* `users` existence check, so grants alone allow.
|
|
17
|
+
*
|
|
18
|
+
* ## Naming conventions
|
|
19
|
+
*
|
|
20
|
+
* Every name here follows Ory Permissions' documented conventions
|
|
21
|
+
* (https://www.ory.com/docs/keto/concepts/namespaces#naming-conventions):
|
|
22
|
+
*
|
|
23
|
+
* - **Namespaces** are TypeScript classes named after the **singular** form of
|
|
24
|
+
* the type they describe, in UpperCamelCase — `AgentTool`, `ShellTool`,
|
|
25
|
+
* `Delegation`, `PermissionMode`, `User`, `Agent`, `SubAgent`, `Session`.
|
|
26
|
+
* - **Relations** are **plural** nouns naming the set of subjects on the far end
|
|
27
|
+
* of the edge, so each reads as an English sentence — `User:bob is in users of
|
|
28
|
+
* AgentTool:Bash`, `Agent:abc is in credentials of Delegation:agent:<join>`.
|
|
29
|
+
* - **Permits** are verbs, like Keto's own `view` — hence `use` for "may this
|
|
30
|
+
* subject use this tool", which is the question the gate actually asks.
|
|
31
|
+
* - A namespace holds a **homogeneous** type of object. That is why delegation
|
|
32
|
+
* nodes and the posture sentinels are *not* tool objects: `AgentTool` holds
|
|
33
|
+
* only tools, `Delegation` only delegation nodes, `PermissionMode` only the
|
|
34
|
+
* posture anchors. A single namespace holding all three is the case the
|
|
35
|
+
* convention doc calls out as incorrect, and it forced one class to carry a
|
|
36
|
+
* grab bag of unrelated relations.
|
|
37
|
+
*
|
|
38
|
+
* A relation and a permit cannot share a name in OPL — which is exactly why the
|
|
39
|
+
* grant relation is the plural `users` and the permit the singular verb `use`.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* The relation that grants a subject use of a tool object — the set of subjects
|
|
43
|
+
* that may use it. Written in the Ory Console (Agent Security); the plugin only
|
|
44
|
+
* ever reads it. Reads as `User:bob is in users of AgentTool:Bash`.
|
|
45
|
+
*/
|
|
46
|
+
export declare const RELATION_USERS = "users";
|
|
47
|
+
/**
|
|
48
|
+
* The relation that records a delegation edge on a {@link DELEGATION_NAMESPACE}
|
|
49
|
+
* node (`user→agent`, `agent→subagent`) — the set of subjects that delegated to
|
|
50
|
+
* it. Written by the agent-security broker, never by the runtime; declared here
|
|
51
|
+
* so the local Keto mount (which loads this OPL) accepts the tuples.
|
|
52
|
+
*/
|
|
53
|
+
export declare const RELATION_DELEGATES = "delegates";
|
|
54
|
+
/**
|
|
55
|
+
* The relation that explicitly blocks subjects from a tool object
|
|
56
|
+
* (deny-override). A participle has no natural plural, so the relation names the
|
|
57
|
+
* set it holds: `User:bob is in blockedSubjects of AgentTool:curl`.
|
|
58
|
+
*/
|
|
59
|
+
export declare const RELATION_BLOCKED_SUBJECTS = "blockedSubjects";
|
|
60
|
+
/**
|
|
61
|
+
* The relation recording which OAuth2 clients a delegation node ran as:
|
|
62
|
+
* `Delegation:agent:<join>#credentials@(Agent:<clientId>)`. Written by the
|
|
63
|
+
* broker, never by the runtime, and never checked — a delegation node is keyed
|
|
64
|
+
* on (identity, harness, host) so that it survives credential rotation, which
|
|
65
|
+
* means the node alone cannot say which credential acted and two clients for one
|
|
66
|
+
* triple collapse onto it. This edge carries that missing axis, for audit and so
|
|
67
|
+
* a reader can join a node to its client exactly rather than by inference.
|
|
68
|
+
*/
|
|
69
|
+
export declare const RELATION_CREDENTIALS = "credentials";
|
|
70
|
+
/**
|
|
71
|
+
* The relation holding the subjects that are in **enforce** mode. Read (never
|
|
72
|
+
* written by the runtime) via a `checkPermission` on the
|
|
73
|
+
* {@link PERMISSION_MODE_OBJECT} anchor: an admin grants
|
|
74
|
+
* `PermissionMode:mode#enforcedSubjects@<subject>` (directly, or to a
|
|
75
|
+
* subject-set / group for a project-wide flip) to promote that principal from
|
|
76
|
+
* the default `observe` posture to `enforce`. Absence ⇒ `observe`. Named for the
|
|
77
|
+
* set it holds, since `enforce` is a verb and has no plural noun form.
|
|
78
|
+
*/
|
|
79
|
+
export declare const RELATION_ENFORCED_SUBJECTS = "enforcedSubjects";
|
|
80
|
+
/**
|
|
81
|
+
* Default permission namespace / OPL class name for harness tool objects
|
|
82
|
+
* (`AgentTool:Bash`). Singular, because the namespace describes *one tool*, and
|
|
83
|
+
* an object in it is one. Mirrors `ORY_PERMISSION_NAMESPACE`.
|
|
84
|
+
*/
|
|
85
|
+
export declare const DEFAULT_NAMESPACE = "AgentTool";
|
|
86
|
+
/**
|
|
87
|
+
* Default Keto namespace for decomposed shell-command sub-tools (issue #76) —
|
|
88
|
+
* one object per program/builtin word (`ShellTool:curl`). Rendered with the same
|
|
89
|
+
* grant/block model as {@link DEFAULT_NAMESPACE}, so an explicit
|
|
90
|
+
* `ShellTool:curl#blockedSubjects` overrides a `users` grant. Mirrors
|
|
91
|
+
* `resolveShellCommandNamespace()` in tool-catalog.ts.
|
|
92
|
+
*/
|
|
93
|
+
export declare const DEFAULT_SHELL_NAMESPACE = "ShellTool";
|
|
94
|
+
/**
|
|
95
|
+
* Namespace for delegation nodes — the current-state graph of who delegated to
|
|
96
|
+
* whom (`Delegation:agent:<join>`, `Delegation:subagent:<join>|<type>`). Its own
|
|
97
|
+
* namespace because a delegation node is not a tool: mixing the two put
|
|
98
|
+
* heterogeneous objects in one namespace and made the tool class carry
|
|
99
|
+
* delegation relations that no tool object ever uses. The broker owns both the
|
|
100
|
+
* objects and the tuples; the plugin treats a node id as opaque.
|
|
101
|
+
*/
|
|
102
|
+
export declare const DELEGATION_NAMESPACE = "Delegation";
|
|
103
|
+
/**
|
|
104
|
+
* Namespaces for **references to** delegation nodes — the parent pointer on a
|
|
105
|
+
* delegation edge (issue #225).
|
|
106
|
+
*
|
|
107
|
+
* `Agent` and `SubAgent` name a *principal identity*: an OAuth2 client that
|
|
108
|
+
* authenticates, and the subject an admin grants or blocks. A delegation edge's
|
|
109
|
+
* `delegates` subject is a different kind of thing — a pointer at another node
|
|
110
|
+
* in the graph, keyed by `<identity>|<harness>|<host>|<session>`. Both were
|
|
111
|
+
* addressed under `Agent` / `SubAgent`, so one namespace carried two meanings:
|
|
112
|
+
*
|
|
113
|
+
* Agent:<clientId> a principal identity
|
|
114
|
+
* Agent:<identity>|<harness>|<host>|<session> a graph-node reference
|
|
115
|
+
*
|
|
116
|
+
* Nothing written today is ambiguous, because a Hydra client id is a UUID and a
|
|
117
|
+
* join key always contains separators — but that disjointness is a property of
|
|
118
|
+
* the *data*, not of the model, and it is reachable-breakable through
|
|
119
|
+
* `ORY_AGENT_SUBJECT_ID` (guarded separately in #241). The costlier problem is
|
|
120
|
+
* silent: an admin, or a Console UI, that reads a node id off the delegation
|
|
121
|
+
* graph and writes it as a grant subject produces a tuple that is accepted,
|
|
122
|
+
* stored, and never matches any check — the same failure the SubjectSet-vs-
|
|
123
|
+
* SubjectID invariant exists to prevent, one level up. That surface is four
|
|
124
|
+
* relations wide (`users`, `blockedSubjects`, `members`, `enforcedSubjects`).
|
|
125
|
+
*
|
|
126
|
+
* Splitting the two meanings apart makes the wrong-form grant name a namespace
|
|
127
|
+
* that has no `users` relation at all, rather than looking plausible. It also
|
|
128
|
+
* lets the broker's downward walk use the right namespace per level instead of
|
|
129
|
+
* guessing `Agent` for every level — the latent inconsistency that would become
|
|
130
|
+
* a real bug the moment nested sub-agents ship.
|
|
131
|
+
*/
|
|
132
|
+
export declare const AGENT_NODE_NAMESPACE = "AgentNode";
|
|
133
|
+
/** Sub-agent counterpart of {@link AGENT_NODE_NAMESPACE}. */
|
|
134
|
+
export declare const SUBAGENT_NODE_NAMESPACE = "SubAgentNode";
|
|
135
|
+
/**
|
|
136
|
+
* Namespace for the shared role a project grants tools to, rather than granting
|
|
137
|
+
* every identity directly (`AgentRole:agent-security-users#members@(User:<id>)`,
|
|
138
|
+
* with each tool granted to `(AgentRole:agent-security-users#members)`). Written
|
|
139
|
+
* by the Ory Console and the Agent Security broker's enrollment; the plugin only
|
|
140
|
+
* ever resolves it as part of the `use` permit.
|
|
141
|
+
*
|
|
142
|
+
* Its own namespace because a role is not a tool. That is also what makes **one**
|
|
143
|
+
* role tuple enough: while the role was a tool object, a membership had to be
|
|
144
|
+
* written once per tool namespace (Keto matches a subject-set exactly, and the
|
|
145
|
+
* role object's namespace had to be the same as the granting object's), so the
|
|
146
|
+
* same role existed twice and could drift.
|
|
147
|
+
*/
|
|
148
|
+
export declare const AGENT_ROLE_NAMESPACE = "AgentRole";
|
|
149
|
+
/** Group of registered agent credentials sharing a harness key. */
|
|
150
|
+
export declare const AGENT_TYPE_NAMESPACE = "AgentType";
|
|
151
|
+
/** Group of registered sub-agent credentials sharing a type name. */
|
|
152
|
+
export declare const SUBAGENT_TYPE_NAMESPACE = "SubAgentType";
|
|
153
|
+
/** The relation naming a role's members. Reads as `User:bob is in members of AgentRole:<role>`. */
|
|
154
|
+
export declare const RELATION_MEMBERS = "members";
|
|
155
|
+
/**
|
|
156
|
+
* Namespace for Agent Security enrollment settings — currently whether a newly
|
|
157
|
+
* connected agent's identity is auto-enrolled into the shared role. Stored as an
|
|
158
|
+
* **opt-out** (`Enrollment:autoEnroll#optedOutSubjects@(Enrollment:project#optedOutSubjects)`)
|
|
159
|
+
* so absence means on, which is what a project provisioned before the setting
|
|
160
|
+
* existed reads as. Written and read by the Console and the broker.
|
|
161
|
+
*/
|
|
162
|
+
export declare const ENROLLMENT_NAMESPACE = "Enrollment";
|
|
163
|
+
/** The object the auto-enroll setting hangs off. */
|
|
164
|
+
export declare const AUTO_ENROLL_OBJECT = "autoEnroll";
|
|
165
|
+
/** The relation holding the subjects that opted out of a setting. */
|
|
166
|
+
export declare const RELATION_OPTED_OUT_SUBJECTS = "optedOutSubjects";
|
|
167
|
+
/**
|
|
168
|
+
* Namespace for the server-read deny posture. Its own namespace for the same
|
|
169
|
+
* reason as {@link DELEGATION_NAMESPACE}: the posture anchor is not a tool, and
|
|
170
|
+
* once it stops sharing a namespace with tool names it no longer needs a
|
|
171
|
+
* collision-proof sentinel spelling either — hence the plain
|
|
172
|
+
* {@link PERMISSION_MODE_OBJECT} / {@link PROJECT_POSTURE_OBJECT} object ids
|
|
173
|
+
* rather than the double-underscore guards an earlier release used.
|
|
174
|
+
*/
|
|
175
|
+
export declare const PERMISSION_MODE_NAMESPACE = "PermissionMode";
|
|
176
|
+
/**
|
|
177
|
+
* The object an enforce-mode grant hangs off. The permission mode is resolved as
|
|
178
|
+
* `checkPermission(PermissionMode:mode#enforcedSubjects@<subject>)`.
|
|
179
|
+
*/
|
|
180
|
+
export declare const PERMISSION_MODE_OBJECT = "mode";
|
|
181
|
+
/**
|
|
182
|
+
* Object standing in for **every principal on the project**, used as the subject
|
|
183
|
+
* of a project-wide posture grant:
|
|
184
|
+
*
|
|
185
|
+
* PermissionMode:mode#enforcedSubjects@(PermissionMode:project#enforcedSubjects)
|
|
186
|
+
*
|
|
187
|
+
* Keto has no wildcard subject, and a per-principal grant cannot cover a
|
|
188
|
+
* principal that does not exist yet — so an agent connecting after an admin
|
|
189
|
+
* turned on enforce would resolve `observe` and silently escape enforcement
|
|
190
|
+
* until someone re-applied the grant for it. Checking this fixed sentinel first
|
|
191
|
+
* makes the posture a property of the project: one relation governs every
|
|
192
|
+
* principal, present and future. Per-principal grants remain meaningful as
|
|
193
|
+
* exceptions (enforce one user while the project is still observing).
|
|
194
|
+
*/
|
|
195
|
+
export declare const PROJECT_POSTURE_OBJECT = "project";
|
|
196
|
+
/**
|
|
197
|
+
* The permit Argus checks: `users && !blockedSubjects`, evaluated natively by
|
|
198
|
+
* Keto. A verb, as Keto's own `view` is — it names the question the gate asks.
|
|
199
|
+
*/
|
|
200
|
+
export declare const PERMIT_USE = "use";
|
|
201
|
+
/**
|
|
202
|
+
* The module OPL sources import their type symbols from. Keto's parser
|
|
203
|
+
* recognizes this name (and the equivalent `@ory/permission-namespace-types`)
|
|
204
|
+
* and strips the import — no npm dependency is pulled at runtime.
|
|
205
|
+
*/
|
|
206
|
+
export declare const OPL_IMPORT_MODULE = "@ory/keto-namespace-types";
|
|
207
|
+
/**
|
|
208
|
+
* Every type symbol the rendered OPL references, and therefore must import:
|
|
209
|
+
* `Namespace` (every class implements it), `SubjectSet` (the relation unions
|
|
210
|
+
* allow set expansion), and `Context` (the `use` permit is typed
|
|
211
|
+
* `(ctx: Context)`). This is the canonical set — any code that assembles or
|
|
212
|
+
* merges the OPL imports exactly these.
|
|
213
|
+
*/
|
|
214
|
+
export declare const OPL_IMPORT_SYMBOLS: readonly ["Namespace", "SubjectSet", "Context"];
|
|
215
|
+
/**
|
|
216
|
+
* The principal namespaces every subject is addressed under (SubjectSets):
|
|
217
|
+
* `User`, `Agent`, `SubAgent`, and the `Session` fallback. The object
|
|
218
|
+
* namespaces' relations are typed by them, so they must be defined for checks to
|
|
219
|
+
* resolve rather than `NotFound`.
|
|
220
|
+
*
|
|
221
|
+
* These are **identities** — things that authenticate and that an admin can
|
|
222
|
+
* grant or block. Graph-node references are a separate kind and live in
|
|
223
|
+
* {@link NODE_REFERENCE_NAMESPACES}; keeping the two lists apart is what stops a
|
|
224
|
+
* node id from being written where an identity belongs (#225).
|
|
225
|
+
*/
|
|
226
|
+
export declare const PRINCIPAL_NAMESPACES: readonly ["User", "Agent", "SubAgent", "Session"];
|
|
227
|
+
/**
|
|
228
|
+
* Namespaces holding references to delegation-graph nodes. Declared so the
|
|
229
|
+
* `delegates` relation that is typed by them resolves, and deliberately *not*
|
|
230
|
+
* part of {@link PRINCIPAL_NAMESPACES}: a node reference is never a grant, block,
|
|
231
|
+
* role-membership, or posture subject.
|
|
232
|
+
*/
|
|
233
|
+
export declare const NODE_REFERENCE_NAMESPACES: readonly ["AgentNode", "SubAgentNode"];
|
|
234
|
+
/** Render the canonical import line for a from-scratch OPL file. */
|
|
235
|
+
export declare function renderOplImport(): string;
|
|
236
|
+
/** Render a principal-namespace class (an empty `implements Namespace`). */
|
|
237
|
+
export declare function renderPrincipalClass(name: string): string;
|
|
238
|
+
/**
|
|
239
|
+
* Render a tool-namespace class body: the `users` grant, the `blockedSubjects`
|
|
240
|
+
* deny-override, and the `use` permit (`users && !blockedSubjects`) Argus
|
|
241
|
+
* checks. The single definition of that class, used for both tool namespaces.
|
|
242
|
+
*/
|
|
243
|
+
export declare function renderToolNamespaceClass(namespace?: string): string;
|
|
244
|
+
/**
|
|
245
|
+
* Render the delegation-node class: who delegated to this node, and which OAuth2
|
|
246
|
+
* clients it ran as. Nothing is ever checked here — the graph is an audit trail —
|
|
247
|
+
* but the relations must be declared for the broker's writes to be accepted.
|
|
248
|
+
*/
|
|
249
|
+
export declare function renderDelegationNamespaceClass(namespace?: string): string;
|
|
250
|
+
/**
|
|
251
|
+
* Render the role class: the members of a shared role a project grants tools to.
|
|
252
|
+
* One class, one relation — a role is a group of subjects and nothing else.
|
|
253
|
+
*/
|
|
254
|
+
export declare function renderAgentRoleNamespaceClass(namespace?: string): string;
|
|
255
|
+
/** Render a harness/sub-agent type group whose members inherit posture. */
|
|
256
|
+
export declare function renderAgentTypeNamespaceClass(namespace: string, memberNamespace: string): string;
|
|
257
|
+
/**
|
|
258
|
+
* Render the enrollment-settings class: which subjects opted out of a setting.
|
|
259
|
+
* An opt-out rather than an opt-in, so absence reads as "on".
|
|
260
|
+
*/
|
|
261
|
+
export declare function renderEnrollmentNamespaceClass(namespace?: string): string;
|
|
262
|
+
/**
|
|
263
|
+
* Render the permission-mode class: the set of subjects an admin has promoted
|
|
264
|
+
* from `observe` to `enforce`. One relation, read by every gate.
|
|
265
|
+
*/
|
|
266
|
+
export declare function renderPermissionModeNamespaceClass(namespace?: string): string;
|
|
267
|
+
/**
|
|
268
|
+
* Render the complete OPL namespace-definition file for the Agent Security
|
|
269
|
+
* model.
|
|
270
|
+
*
|
|
271
|
+
* This is the model an Ory project must have for Agent Security checks to
|
|
272
|
+
* resolve. On a hosted project it is applied in the Ory Console (Agent
|
|
273
|
+
* Security) — the plugin never pushes it. This renderer exists so the **local
|
|
274
|
+
* dev stack** can mount the identical definition into its own Keto config,
|
|
275
|
+
* keeping local and hosted on one definition, and so the model can be printed
|
|
276
|
+
* for reference.
|
|
277
|
+
*
|
|
278
|
+
* `namespace` is the tool namespace (OPL class name); defaults to
|
|
279
|
+
* {@link DEFAULT_NAMESPACE}. Operators who override `ORY_PERMISSION_NAMESPACE`
|
|
280
|
+
* must provision the schema under the same name so the class the checks address
|
|
281
|
+
* exists. The `Delegation` and `PermissionMode` namespaces are not
|
|
282
|
+
* operator-configurable — they hold project-wide state, not per-deployment tool
|
|
283
|
+
* objects.
|
|
284
|
+
*
|
|
285
|
+
* The output is the TypeScript-flavored OPL source Keto parses (the import is
|
|
286
|
+
* recognized and stripped by Keto's parser — no npm dependency is pulled at
|
|
287
|
+
* runtime). It is written verbatim into the local stack's keto config mount.
|
|
288
|
+
*/
|
|
289
|
+
export declare function buildAgentSecurityOpl(namespace?: string, shellNamespace?: string): string;
|