@ory/argus 0.14.0 → 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.
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 +408 -0
  90. package/dist/runtime.js +748 -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,307 @@
1
+ "use strict";
2
+ /**
3
+ * Server-read permission mode.
4
+ *
5
+ * `observe` vs `enforce` is no longer a local, per-machine setting — it is a
6
+ * **permission the plugin reads from Keto** before gating a tool call, so an
7
+ * admin controls the deny posture centrally from the Ory project (Ory Console /
8
+ * Agent Security), and every session inherits it. There is no local override
9
+ * and no `ORY_PERMISSION_MODE` env var.
10
+ *
11
+ * The mode lives in its own `PermissionMode` namespace — it is not a tool, so it
12
+ * is not a tool object (see the naming-conventions note in `opl.ts`). It is
13
+ * resolved by `checkPermission` against the `mode` anchor, at two scopes:
14
+ *
15
+ * project: PermissionMode:mode#enforcedSubjects@(PermissionMode:project#enforcedSubjects)
16
+ * applicable: PermissionMode:mode#enforcedSubjects@<identity|agent|subagent>
17
+ * allowed ⇒ enforce denied ⇒ observe
18
+ *
19
+ * The **project** grant is checked first and is the posture an admin normally
20
+ * sets: one tuple governs every principal, including ones that do not exist
21
+ * yet. That matters because a per-principal grant cannot cover a future
22
+ * principal — before the project scope existed, an agent connecting after an
23
+ * admin turned on enforce resolved `observe` and silently escaped enforcement
24
+ * until someone re-applied the grant for it. A **per-principal** grant remains
25
+ * meaningful as an exception: enforce one identity, agent harness, or sub-agent
26
+ * type while the project still observes. Type grants are inherited through the
27
+ * server-managed AgentType/SubAgentType membership relations.
28
+ * Neither scope can be set by the runtime — the plugin only ever reads, riding
29
+ * its own OAuth2 access token like every other Keto read.
30
+ *
31
+ * Resolution precedence, applied by {@link resolvePermissionMode}:
32
+ *
33
+ * 1. **In-memory TTL cache** (per scope) — avoids a Keto round-trip on
34
+ * literally every tool call while still re-reading the server every `ttlMs()`.
35
+ * The project scope caches under one key shared by every subject, so the
36
+ * common "whole project enforced" case costs a single read per TTL window.
37
+ * 2. **Server check** — project scope, then identity and acting machine scopes
38
+ * only if the project is not enforcing. On a clean result, refresh the in-memory cache
39
+ * and return it (`source: "server"`).
40
+ * 3. **Persistent cache** — when the server is unreachable, fall back to the
41
+ * last value read from the server, persisted in `config.json`
42
+ * (`source: "cache"`).
43
+ * 4. **`observe`** — nothing was ever cached (`source: "default"`).
44
+ *
45
+ * The persistent cache is written by {@link warmPermissionModeCache} at session
46
+ * start and when a gate first discovers a new acting-machine scope. It only
47
+ * writes when a cached mode changes, so normal per-tool checks do not churn the
48
+ * shared config while child-only posture still survives subprocess boundaries.
49
+ */
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.resetPermissionModeCache = resetPermissionModeCache;
52
+ exports.resolvePermissionMode = resolvePermissionMode;
53
+ exports.warmPermissionModeCache = warmPermissionModeCache;
54
+ const config_js_1 = require("./config.js");
55
+ const read_credential_js_1 = require("./read-credential.js");
56
+ const opl_js_1 = require("./opl.js");
57
+ /**
58
+ * Default in-memory cache TTL (ms). Small enough that an admin's mode change is
59
+ * picked up within a session without a restart, large enough that a burst of
60
+ * tool calls doesn't issue a Keto read each. Override with
61
+ * `ORY_PERMISSION_MODE_TTL_MS`.
62
+ */
63
+ const DEFAULT_TTL_MS = 30_000;
64
+ function ttlMs() {
65
+ const raw = process.env.ORY_PERMISSION_MODE_TTL_MS;
66
+ if (!raw)
67
+ return DEFAULT_TTL_MS;
68
+ const n = Number.parseInt(raw, 10);
69
+ if (!Number.isFinite(n) || n < 0)
70
+ return DEFAULT_TTL_MS;
71
+ return n;
72
+ }
73
+ /**
74
+ * The posture is read from the fixed `PermissionMode` namespace, **not** the tool
75
+ * namespace: `ORY_PERMISSION_NAMESPACE` names where an operator's *tool* objects
76
+ * live, and the deny posture is a property of the project rather than of any one
77
+ * tool namespace. Keeping it fixed also means the two tool namespaces
78
+ * (`AgentTool`, `ShellTool`) can never disagree about the posture.
79
+ */
80
+ function resolveNamespace() {
81
+ return opl_js_1.PERMISSION_MODE_NAMESPACE;
82
+ }
83
+ /**
84
+ * In-memory cache, keyed **by client** (so it is scoped to one session's
85
+ * lifecycle) and then by subject. A `WeakMap` means a discarded client's cache
86
+ * is collected with it — and, crucially, that each test's fresh client starts
87
+ * with an empty cache, so no stale mode bleeds across tests.
88
+ */
89
+ let clientMemo = new WeakMap();
90
+ function memoFor(client) {
91
+ let m = clientMemo.get(client);
92
+ if (!m) {
93
+ m = new Map();
94
+ clientMemo.set(client, m);
95
+ }
96
+ return m;
97
+ }
98
+ function subjectKey(subject) {
99
+ if (subject.subjectId)
100
+ return `id:${subject.subjectId}`;
101
+ const s = subject.subjectSet;
102
+ if (s)
103
+ return `set:${s.namespace}:${s.object}#${s.relation}`;
104
+ return "anon";
105
+ }
106
+ /**
107
+ * Cache key for the project-scope read. Distinct from every {@link subjectKey}
108
+ * (which is always `id:`/`set:`/`anon`-prefixed) and shared by all subjects, so
109
+ * one read per TTL window covers the whole session.
110
+ */
111
+ const PROJECT_SCOPE_KEY = "project";
112
+ /** The sentinel subject a project-wide posture grant is written to. */
113
+ function projectPostureSubject(namespace) {
114
+ return {
115
+ subjectSet: {
116
+ namespace,
117
+ object: opl_js_1.PROJECT_POSTURE_OBJECT,
118
+ relation: opl_js_1.RELATION_ENFORCED_SUBJECTS,
119
+ },
120
+ };
121
+ }
122
+ /** Drop all in-memory caches. Test-only (reassigns the WeakMap). */
123
+ function resetPermissionModeCache() {
124
+ clientMemo = new WeakMap();
125
+ }
126
+ /**
127
+ * Resolve the current permission mode for `subject`. Never throws — a Keto
128
+ * error falls back to the persistent cache, then `observe`. See the module
129
+ * doc for the precedence. Does **not** persist (that is
130
+ * {@link warmPermissionModeCache}'s job); `opts.now` is injectable for tests.
131
+ */
132
+ async function resolvePermissionMode(client, subject, opts = {}) {
133
+ const now = opts.now ?? Date.now();
134
+ const projectUrl = (0, config_js_1.resolveConfig)().projectUrl;
135
+ const namespace = resolveNamespace();
136
+ const key = subjectKey(subject);
137
+ const subjects = [
138
+ { subject, scope: "principal", key },
139
+ ...(opts.additionalSubjects ?? []).map((item) => ({
140
+ ...item,
141
+ key: subjectKey(item.subject),
142
+ })),
143
+ ].filter((item, index, all) => all.findIndex((candidate) => candidate.key === item.key) === index);
144
+ const memo = memoFor(client);
145
+ const fresh = (cacheKey) => {
146
+ const entry = memo.get(cacheKey);
147
+ if (entry && now - entry.fetchedAt < ttlMs())
148
+ return entry;
149
+ memo.delete(cacheKey);
150
+ return undefined;
151
+ };
152
+ // An enforcing project settles the mode for every subject, so a fresh project
153
+ // hit short-circuits before the subject is even considered.
154
+ const cachedProject = fresh(PROJECT_SCOPE_KEY);
155
+ if (cachedProject?.mode === "enforce") {
156
+ return { mode: "enforce", source: cachedProject.source };
157
+ }
158
+ const cachedSubjects = subjects.map((item) => fresh(item.key));
159
+ if (cachedProject && cachedSubjects.every(Boolean)) {
160
+ const enforcing = cachedSubjects.find((entry) => entry?.mode === "enforce");
161
+ return { mode: enforcing?.mode ?? "observe", source: enforcing?.source ?? cachedProject.source };
162
+ }
163
+ // The mode is read from the project, so it needs the same authenticated Keto
164
+ // read a tool check does. Without this a subprocess event past the user
165
+ // token's hour read nothing and fell back to the `observe` default — silently
166
+ // un-enforcing an `enforce` project (#242). After the short-circuits above, so
167
+ // a cache hit costs nothing.
168
+ await (0, read_credential_js_1.ensureReadCredential)(client);
169
+ const check = async (scope, modeSubject, cacheKey) => {
170
+ const result = await client.checkPermission({
171
+ namespace,
172
+ object: opl_js_1.PERMISSION_MODE_OBJECT,
173
+ relation: opl_js_1.RELATION_ENFORCED_SUBJECTS,
174
+ ...modeSubject,
175
+ }, {
176
+ // This is a mode *read*, not a gate: a `false` result selects `observe`,
177
+ // it is not a tool denial. Mark it informational so the event ends `ok`
178
+ // and carry a note explaining the boolean, so live debug output is
179
+ // self-explanatory rather than looking like a blocked tool.
180
+ informational: true,
181
+ activityAttributes: {
182
+ source: "permission_mode",
183
+ scope,
184
+ note: "mode read — allowed=true ⇒ enforce, allowed=false ⇒ observe",
185
+ },
186
+ });
187
+ const mode = result.allowed ? "enforce" : "observe";
188
+ memo.set(cacheKey, { mode, source: "server", fetchedAt: now });
189
+ return mode;
190
+ };
191
+ try {
192
+ const projectMode = cachedProject?.mode
193
+ ?? (await check("project", projectPostureSubject(namespace), PROJECT_SCOPE_KEY));
194
+ let scope = "project";
195
+ let mode = projectMode;
196
+ if (projectMode !== "enforce") {
197
+ mode = "observe";
198
+ for (const [index, item] of subjects.entries()) {
199
+ const subjectMode = cachedSubjects[index]?.mode ?? (await check(item.scope, item.subject, item.key));
200
+ if (subjectMode === "enforce") {
201
+ mode = subjectMode;
202
+ scope = item.scope;
203
+ break;
204
+ }
205
+ }
206
+ if (mode === "observe")
207
+ scope = "principal";
208
+ }
209
+ client.logger.activity("permission.mode_resolve", "ok", {
210
+ attributes: {
211
+ permissionMode: mode,
212
+ enforceGranted: mode === "enforce",
213
+ scope,
214
+ source: "server",
215
+ },
216
+ });
217
+ return { mode, source: "server" };
218
+ }
219
+ catch (err) {
220
+ const oryErr = err;
221
+ const cache = (0, config_js_1.resolveConfig)().permissionModeCache;
222
+ const scoped = cache && cache.projectUrl === projectUrl ? cache.scopes : undefined;
223
+ const project = scoped?.[PROJECT_SCOPE_KEY];
224
+ const subjectEntries = subjects.map((item) => scoped?.[item.key]);
225
+ const scopedMode = project?.mode === "enforce" || subjectEntries.some((entry) => entry?.mode === "enforce")
226
+ ? "enforce"
227
+ : project && subjectEntries.every(Boolean)
228
+ ? "observe"
229
+ : undefined;
230
+ // A legacy scalar enforce value is a conservative fallback for every scope.
231
+ // A scalar observe value is not: it may have been written for a different
232
+ // identity or harness and must not silently relax that scope.
233
+ const legacyMode = cache && !cache.scopes && (!cache.projectUrl || cache.projectUrl === projectUrl)
234
+ ? cache.mode
235
+ : undefined;
236
+ const cachedMode = scopedMode ?? (legacyMode === "enforce" ? "enforce" : undefined);
237
+ if (cachedMode) {
238
+ client.logger.debug("permission.mode_cache", {
239
+ code: oryErr?.code,
240
+ note: "mode check failed; using last cached server value",
241
+ mode: cachedMode,
242
+ });
243
+ return { mode: cachedMode, source: "cache" };
244
+ }
245
+ client.logger.debug("permission.mode_default", {
246
+ code: oryErr?.code,
247
+ note: "mode check failed and no cached value; defaulting to observe",
248
+ });
249
+ return { mode: "observe", source: "default" };
250
+ }
251
+ }
252
+ /**
253
+ * Resolve the mode and, when it came from a live server read, persist it to
254
+ * `config.json` so a subprocess harness's later hook processes (and the
255
+ * synchronous MCP `applyPermissionMode` path) see the current posture, and so a
256
+ * subsequent offline session has a cached value to fall back to. Called once at
257
+ * session start. Best-effort; never throws. Only writes when the value changed,
258
+ * so it doesn't churn the config lockfile.
259
+ */
260
+ async function warmPermissionModeCache(client, subject, opts = {}) {
261
+ const now = opts.now ?? Date.now();
262
+ const projectUrl = (0, config_js_1.resolveConfig)().projectUrl;
263
+ const resolved = await resolvePermissionMode(client, subject, {
264
+ now,
265
+ additionalSubjects: opts.additionalSubjects,
266
+ });
267
+ if (resolved.source === "server") {
268
+ const requestedKeys = [PROJECT_SCOPE_KEY, subjectKey(subject), ...(opts.additionalSubjects ?? []).map((item) => subjectKey(item.subject))];
269
+ const updates = {};
270
+ for (const key of new Set(requestedKeys)) {
271
+ const entry = memoFor(client).get(key);
272
+ if (entry?.source === "server")
273
+ updates[key] = { mode: entry.mode, fetchedAt: entry.fetchedAt };
274
+ }
275
+ try {
276
+ (0, config_js_1.mutateConfig)((config) => {
277
+ const current = config.permissionModeCache;
278
+ const scopes = { ...(current && current.projectUrl === projectUrl ? current.scopes ?? {} : {}) };
279
+ const projectMode = updates[PROJECT_SCOPE_KEY]?.mode
280
+ ?? scopes[PROJECT_SCOPE_KEY]?.mode
281
+ ?? "observe";
282
+ let changed = current?.mode !== projectMode || current?.projectUrl !== projectUrl;
283
+ for (const [key, entry] of Object.entries(updates)) {
284
+ const refreshed = { mode: entry.mode, fetchedAt: now };
285
+ if (scopes[key]?.mode === refreshed.mode && scopes[key]?.fetchedAt === refreshed.fetchedAt)
286
+ continue;
287
+ scopes[key] = refreshed;
288
+ changed = true;
289
+ }
290
+ if (!changed)
291
+ return undefined;
292
+ const boundedScopes = Object.fromEntries(Object.entries(scopes)
293
+ .sort(([, left], [, right]) => right.fetchedAt - left.fetchedAt)
294
+ .slice(0, 256));
295
+ return {
296
+ ...config,
297
+ permissionModeCache: { mode: projectMode, fetchedAt: now, projectUrl, scopes: boundedScopes },
298
+ };
299
+ });
300
+ }
301
+ catch {
302
+ // Best-effort — a write failure just means the next process re-reads
303
+ // from the server (or starts at observe until it can).
304
+ }
305
+ }
306
+ return resolved;
307
+ }
@@ -1,24 +1,20 @@
1
1
  /**
2
2
  * Shared `permissions` CLI implementation. Each harness's `cli/main.ts`
3
- * delegates to {@link runPermissionsCommand}, passing the harness's name
4
- * so subcommands can scope to that harness's tool catalog.
3
+ * delegates to {@link runPermissionsCommand}, passing the harness's name so the
4
+ * report can scope to that harness's tool catalog.
5
5
  *
6
- * Subcommands:
6
+ * `permissions` takes **no subcommand** — it is a single read-only report: the
7
+ * live permission mode (read from the Ory project), the subject being checked,
8
+ * and the allow / deny / blocked breakdown across the harness's known tool
9
+ * catalog. (`permissions status` is still accepted; it was the name through
10
+ * v0.14, and the report is the same.)
7
11
  *
8
- * - `status` — Print the configured {@link PermissionMode} and, when
9
- * the client can reach Ory, the allow/deny breakdown
10
- * across the harness's known tool catalog.
11
- * - `bootstrap`Idempotently write `<namespace>:<tool>#use@<userSubject>`
12
- * tuples for every tool in the harness's catalog. Run
13
- * automatically by `install` when a user identity is
14
- * cached; can be re-run by hand any time.
15
- * - `observe` — Persist `permissionMode = "observe"` in the shared
16
- * config (denies log but don't block).
17
- * - `enforce` — Persist `permissionMode = "enforce"` in the shared
18
- * config (denies block — the production posture).
19
- *
20
- * All four are non-destructive on existing config and idempotent on
21
- * Keto: re-running them is always safe.
12
+ * Everything that *writes* to the project is provisioned in the **Ory Console**
13
+ * (Agent Security), not from the plugin: the permission model, the per-tool
14
+ * grants, explicit blocks, and the observe/enforce posture. That is what lets a
15
+ * plugin be installed with nothing but a project URL the public OAuth2 client
16
+ * id has a reserved default, with no workspace privilege, project API key, or admin write path. The
17
+ * plugin is a read-only client of the project's permission state.
22
18
  */
23
19
  /**
24
20
  * Entry point invoked by each harness CLI's `permissions` case.
@@ -28,35 +24,3 @@
28
24
  * exit so the parent CLI doesn't need a try/catch.
29
25
  */
30
26
  export declare function runPermissionsCommand(binName: string, harness: string, args: string[]): Promise<number>;
31
- /**
32
- * Whether a user identity is cached locally — used by `install` to
33
- * decide whether to opportunistically bootstrap tuples without
34
- * prompting. Returns true when persisted tokens exist and are not
35
- * expired, or when ORY_USER_SUBJECT_ID is set explicitly.
36
- */
37
- export declare function isUserIdentityCached(): boolean;
38
- /**
39
- * Print the "permission mode" section of the install banner.
40
- *
41
- * Tells the user what observe vs enforce mean, and prints the two
42
- * follow-up commands they'll typically reach for next:
43
- *
44
- * - `<bin> permissions bootstrap` to seed tuples for the harness's
45
- * built-in tools (the line is shown whether or not we just ran it
46
- * ourselves, so the user can re-run after editing the catalog).
47
- * - `<bin> permissions enforce` once they're satisfied with the
48
- * observe-mode trace output and want denies to actually block.
49
- */
50
- export declare function printPermissionsOnboardingHelp(binName: string, harness: string, opts?: {
51
- bootstrappedAutomatically?: boolean;
52
- }): void;
53
- /**
54
- * If a user identity is already cached and the plugin is configured,
55
- * opportunistically run `permissions bootstrap` so the user lands in a
56
- * "tools work out of the box" state. Otherwise a no-op (the install
57
- * banner still prints the manual command).
58
- *
59
- * Always best-effort: any failure is logged and swallowed so install
60
- * never aborts because of a permissions write problem.
61
- */
62
- export declare function maybeAutoBootstrap(binName: string, harness: string): Promise<boolean>;