@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.
Files changed (150) hide show
  1. package/README.md +31 -46
  2. package/assets/commands/temporal-up.md +1 -1
  3. package/assets/skills/auth-setup/SKILL.md +1 -1
  4. package/assets/skills/local-dev/SKILL.md +17 -7
  5. package/assets/skills/ory-build-agent/SKILL.md +39 -91
  6. package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -17
  7. package/assets/skills/ory-temporal-worker/SKILL.md +31 -33
  8. package/assets/skills/permissions-onboarding/SKILL.md +131 -104
  9. package/dist/adapters.d.ts +88 -32
  10. package/dist/adapters.js +443 -164
  11. package/dist/agent-auth.d.ts +226 -67
  12. package/dist/agent-auth.js +951 -205
  13. package/dist/auth-store.d.ts +37 -2
  14. package/dist/auth-store.js +37 -3
  15. package/dist/auth.d.ts +33 -4
  16. package/dist/auth.js +163 -20
  17. package/dist/bash-parser.d.ts +98 -0
  18. package/dist/bash-parser.js +396 -0
  19. package/dist/branding.d.ts +77 -16
  20. package/dist/branding.js +93 -23
  21. package/dist/build-info.json +4 -4
  22. package/dist/cli-invocation.d.ts +1 -1
  23. package/dist/cli-invocation.js +2 -1
  24. package/dist/cli.d.ts +20 -29
  25. package/dist/cli.js +271 -239
  26. package/dist/client.d.ts +175 -138
  27. package/dist/client.js +672 -391
  28. package/dist/config.d.ts +217 -54
  29. package/dist/config.js +461 -42
  30. package/dist/context.d.ts +10 -0
  31. package/dist/context.js +21 -0
  32. package/dist/contract-suite.d.ts +3 -5
  33. package/dist/contract-suite.js +75 -47
  34. package/dist/denial.d.ts +36 -3
  35. package/dist/denial.js +79 -10
  36. package/dist/event-reporter.d.ts +77 -0
  37. package/dist/event-reporter.js +776 -0
  38. package/dist/external-registrations-main.d.ts +10 -0
  39. package/dist/external-registrations-main.js +38 -0
  40. package/dist/external-registrations.d.ts +79 -0
  41. package/dist/external-registrations.js +188 -0
  42. package/dist/help-cli.d.ts +39 -0
  43. package/dist/help-cli.js +55 -0
  44. package/dist/hook-timeout.d.ts +64 -0
  45. package/dist/hook-timeout.js +88 -0
  46. package/dist/index.d.ts +28 -23
  47. package/dist/index.js +173 -58
  48. package/dist/lifecycle.d.ts +3 -3
  49. package/dist/lifecycle.js +38 -6
  50. package/dist/local/cli.js +11 -6
  51. package/dist/local/configs.d.ts +74 -18
  52. package/dist/local/configs.js +291 -84
  53. package/dist/local/health.js +7 -7
  54. package/dist/local/index.d.ts +2 -2
  55. package/dist/local/index.js +24 -10
  56. package/dist/local/manager.d.ts +20 -1
  57. package/dist/local/manager.js +159 -36
  58. package/dist/local/ports.d.ts +158 -0
  59. package/dist/local/ports.js +443 -0
  60. package/dist/local/seed.d.ts +13 -5
  61. package/dist/local/seed.js +62 -38
  62. package/dist/logger.d.ts +54 -25
  63. package/dist/logger.js +329 -63
  64. package/dist/mcp.d.ts +2 -2
  65. package/dist/mcp.js +10 -5
  66. package/dist/mirror-bootstrap.d.ts +48 -0
  67. package/dist/mirror-bootstrap.js +254 -0
  68. package/dist/opl.d.ts +289 -0
  69. package/dist/opl.js +446 -0
  70. package/dist/permission-mode.d.ts +87 -0
  71. package/dist/permission-mode.js +307 -0
  72. package/dist/permissions-cli.d.ts +13 -49
  73. package/dist/permissions-cli.js +154 -348
  74. package/dist/permissions.d.ts +148 -38
  75. package/dist/permissions.js +591 -45
  76. package/dist/post-install.d.ts +33 -0
  77. package/dist/post-install.js +127 -0
  78. package/dist/read-credential.d.ts +65 -0
  79. package/dist/read-credential.js +86 -0
  80. package/dist/registry/cli.js +5 -2
  81. package/dist/registry/config.d.ts +0 -17
  82. package/dist/registry/config.js +0 -23
  83. package/dist/registry/index.d.ts +1 -1
  84. package/dist/registry/index.js +2 -2
  85. package/dist/registry/manager.d.ts +4 -21
  86. package/dist/registry/manager.js +21 -37
  87. package/dist/runtime-credential.d.ts +140 -0
  88. package/dist/runtime-credential.js +572 -0
  89. package/dist/runtime.d.ts +413 -0
  90. package/dist/runtime.js +825 -0
  91. package/dist/setup.d.ts +23 -47
  92. package/dist/setup.js +59 -116
  93. package/dist/skills.js +0 -7
  94. package/dist/status-cli.d.ts +27 -11
  95. package/dist/status-cli.js +121 -115
  96. package/dist/status-data.d.ts +116 -17
  97. package/dist/status-data.js +121 -38
  98. package/dist/subject.d.ts +126 -20
  99. package/dist/subject.js +215 -30
  100. package/dist/testing.d.ts +74 -38
  101. package/dist/testing.js +185 -68
  102. package/dist/tool-catalog.d.ts +53 -11
  103. package/dist/tool-catalog.js +164 -13
  104. package/dist/tool-metadata.d.ts +7 -6
  105. package/dist/tool-metadata.js +6 -5
  106. package/dist/types.d.ts +11 -1
  107. package/dist/uninstall.d.ts +71 -34
  108. package/dist/uninstall.js +217 -85
  109. package/dist/user-login.d.ts +9 -10
  110. package/dist/user-login.js +56 -75
  111. package/dist/watch-cli.d.ts +6 -0
  112. package/dist/watch-cli.js +217 -0
  113. package/package.json +4 -27
  114. package/assets/commands/dashboard.md +0 -34
  115. package/dist/dashboard-cli.d.ts +0 -8
  116. package/dist/dashboard-cli.js +0 -70
  117. package/dist/dev.d.ts +0 -103
  118. package/dist/dev.js +0 -583
  119. package/dist/interactive-setup.d.ts +0 -286
  120. package/dist/interactive-setup.js +0 -1734
  121. package/dist/local/jaeger-main.d.ts +0 -13
  122. package/dist/local/jaeger-main.js +0 -85
  123. package/dist/local/jaeger.d.ts +0 -50
  124. package/dist/local/jaeger.js +0 -162
  125. package/dist/otel/exporter.d.ts +0 -17
  126. package/dist/otel/exporter.js +0 -12
  127. package/dist/otel/index.d.ts +0 -2
  128. package/dist/otel/index.js +0 -8
  129. package/dist/otel/otlp.d.ts +0 -103
  130. package/dist/otel/otlp.js +0 -385
  131. package/dist/project-api-key.d.ts +0 -69
  132. package/dist/project-api-key.js +0 -147
  133. package/dist/setup-actions.d.ts +0 -232
  134. package/dist/setup-actions.js +0 -507
  135. package/dist/tracer.d.ts +0 -190
  136. package/dist/tracer.js +0 -481
  137. package/dist/watch-sandbox.d.ts +0 -9
  138. package/dist/watch-sandbox.js +0 -81
  139. package/dist/web/api.d.ts +0 -33
  140. package/dist/web/api.js +0 -294
  141. package/dist/web/launch.d.ts +0 -11
  142. package/dist/web/launch.js +0 -96
  143. package/dist/web/server.d.ts +0 -20
  144. package/dist/web/server.js +0 -233
  145. package/dist/web/types.d.ts +0 -65
  146. package/dist/web/types.js +0 -2
  147. package/dist/webapp/assets/index-Wucl4SZs.css +0 -1
  148. package/dist/webapp/assets/index-m-GtEdq0.js +0 -49
  149. package/dist/webapp/favicon.ico +0 -0
  150. package/dist/webapp/index.html +0 -15
@@ -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;