@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.
- package/README.md +31 -46
- package/assets/commands/temporal-up.md +1 -1
- package/assets/skills/auth-setup/SKILL.md +1 -1
- package/assets/skills/local-dev/SKILL.md +17 -7
- package/assets/skills/ory-build-agent/SKILL.md +39 -91
- package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -17
- package/assets/skills/ory-temporal-worker/SKILL.md +31 -33
- package/assets/skills/permissions-onboarding/SKILL.md +131 -104
- package/dist/adapters.d.ts +88 -32
- package/dist/adapters.js +443 -164
- package/dist/agent-auth.d.ts +226 -67
- package/dist/agent-auth.js +951 -205
- package/dist/auth-store.d.ts +37 -2
- package/dist/auth-store.js +37 -3
- package/dist/auth.d.ts +33 -4
- package/dist/auth.js +163 -20
- package/dist/bash-parser.d.ts +98 -0
- package/dist/bash-parser.js +396 -0
- package/dist/branding.d.ts +77 -16
- package/dist/branding.js +93 -23
- package/dist/build-info.json +4 -4
- package/dist/cli-invocation.d.ts +1 -1
- package/dist/cli-invocation.js +2 -1
- package/dist/cli.d.ts +20 -29
- package/dist/cli.js +271 -239
- package/dist/client.d.ts +175 -138
- package/dist/client.js +672 -391
- package/dist/config.d.ts +217 -54
- package/dist/config.js +461 -42
- package/dist/context.d.ts +10 -0
- package/dist/context.js +21 -0
- package/dist/contract-suite.d.ts +3 -5
- package/dist/contract-suite.js +75 -47
- package/dist/denial.d.ts +36 -3
- package/dist/denial.js +79 -10
- package/dist/event-reporter.d.ts +77 -0
- package/dist/event-reporter.js +776 -0
- package/dist/external-registrations-main.d.ts +10 -0
- package/dist/external-registrations-main.js +38 -0
- package/dist/external-registrations.d.ts +79 -0
- package/dist/external-registrations.js +188 -0
- package/dist/help-cli.d.ts +39 -0
- package/dist/help-cli.js +55 -0
- package/dist/hook-timeout.d.ts +64 -0
- package/dist/hook-timeout.js +88 -0
- package/dist/index.d.ts +28 -23
- package/dist/index.js +173 -58
- package/dist/lifecycle.d.ts +3 -3
- package/dist/lifecycle.js +38 -6
- package/dist/local/cli.js +11 -6
- package/dist/local/configs.d.ts +74 -18
- package/dist/local/configs.js +291 -84
- package/dist/local/health.js +7 -7
- package/dist/local/index.d.ts +2 -2
- package/dist/local/index.js +24 -10
- package/dist/local/manager.d.ts +20 -1
- package/dist/local/manager.js +159 -36
- package/dist/local/ports.d.ts +158 -0
- package/dist/local/ports.js +443 -0
- package/dist/local/seed.d.ts +13 -5
- package/dist/local/seed.js +62 -38
- package/dist/logger.d.ts +54 -25
- package/dist/logger.js +329 -63
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +10 -5
- package/dist/mirror-bootstrap.d.ts +48 -0
- package/dist/mirror-bootstrap.js +254 -0
- package/dist/opl.d.ts +289 -0
- package/dist/opl.js +446 -0
- package/dist/permission-mode.d.ts +87 -0
- package/dist/permission-mode.js +307 -0
- package/dist/permissions-cli.d.ts +13 -49
- package/dist/permissions-cli.js +154 -348
- package/dist/permissions.d.ts +148 -38
- package/dist/permissions.js +591 -45
- package/dist/post-install.d.ts +33 -0
- package/dist/post-install.js +127 -0
- package/dist/read-credential.d.ts +65 -0
- package/dist/read-credential.js +86 -0
- package/dist/registry/cli.js +5 -2
- package/dist/registry/config.d.ts +0 -17
- package/dist/registry/config.js +0 -23
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.js +2 -2
- package/dist/registry/manager.d.ts +4 -21
- package/dist/registry/manager.js +21 -37
- package/dist/runtime-credential.d.ts +140 -0
- package/dist/runtime-credential.js +572 -0
- package/dist/runtime.d.ts +408 -0
- package/dist/runtime.js +748 -0
- package/dist/setup.d.ts +23 -47
- package/dist/setup.js +59 -116
- package/dist/skills.js +0 -7
- package/dist/status-cli.d.ts +27 -11
- package/dist/status-cli.js +121 -115
- package/dist/status-data.d.ts +116 -17
- package/dist/status-data.js +121 -38
- package/dist/subject.d.ts +126 -20
- package/dist/subject.js +215 -30
- package/dist/testing.d.ts +74 -38
- package/dist/testing.js +185 -68
- package/dist/tool-catalog.d.ts +53 -11
- package/dist/tool-catalog.js +164 -13
- package/dist/tool-metadata.d.ts +7 -6
- package/dist/tool-metadata.js +6 -5
- package/dist/types.d.ts +11 -1
- package/dist/uninstall.d.ts +71 -34
- package/dist/uninstall.js +217 -85
- package/dist/user-login.d.ts +9 -10
- package/dist/user-login.js +56 -75
- package/dist/watch-cli.d.ts +6 -0
- package/dist/watch-cli.js +217 -0
- package/package.json +4 -27
- package/assets/commands/dashboard.md +0 -34
- package/dist/dashboard-cli.d.ts +0 -8
- package/dist/dashboard-cli.js +0 -70
- package/dist/dev.d.ts +0 -103
- package/dist/dev.js +0 -583
- package/dist/interactive-setup.d.ts +0 -286
- package/dist/interactive-setup.js +0 -1734
- package/dist/local/jaeger-main.d.ts +0 -13
- package/dist/local/jaeger-main.js +0 -85
- package/dist/local/jaeger.d.ts +0 -50
- package/dist/local/jaeger.js +0 -162
- package/dist/otel/exporter.d.ts +0 -17
- package/dist/otel/exporter.js +0 -12
- package/dist/otel/index.d.ts +0 -2
- package/dist/otel/index.js +0 -8
- package/dist/otel/otlp.d.ts +0 -103
- package/dist/otel/otlp.js +0 -385
- package/dist/project-api-key.d.ts +0 -69
- package/dist/project-api-key.js +0 -147
- package/dist/setup-actions.d.ts +0 -232
- package/dist/setup-actions.js +0 -507
- package/dist/tracer.d.ts +0 -190
- package/dist/tracer.js +0 -481
- package/dist/watch-sandbox.d.ts +0 -9
- package/dist/watch-sandbox.js +0 -81
- package/dist/web/api.d.ts +0 -33
- package/dist/web/api.js +0 -294
- package/dist/web/launch.d.ts +0 -11
- package/dist/web/launch.js +0 -96
- package/dist/web/server.d.ts +0 -20
- package/dist/web/server.js +0 -233
- package/dist/web/types.d.ts +0 -65
- package/dist/web/types.js +0 -2
- package/dist/webapp/assets/index-Wucl4SZs.css +0 -1
- package/dist/webapp/assets/index-m-GtEdq0.js +0 -49
- package/dist/webapp/favicon.ico +0 -0
- package/dist/webapp/index.html +0 -15
package/dist/opl.js
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Ory Permission Language (OPL) schema for the Agent Security permission model.
|
|
4
|
+
*
|
|
5
|
+
* Argus relies on more than relation-tuple *existence*: a subject may be granted
|
|
6
|
+
* a tool and separately **blocked** from it, and the block must win. Keto
|
|
7
|
+
* permission is otherwise purely existence-based (no path ⇒ no access, any path
|
|
8
|
+
* ⇒ access), so the deny-override is modeled natively in OPL as a permit:
|
|
9
|
+
*
|
|
10
|
+
* use = users.includes(subject) && !blockedSubjects.includes(subject)
|
|
11
|
+
*
|
|
12
|
+
* Keto evaluates the permit in a single check, so a `blockedSubjects` relation
|
|
13
|
+
* beats a `users` grant no matter how the grant was reached (direct subject or
|
|
14
|
+
* subject-set expansion). Argus always checks the **`use` permit** (see
|
|
15
|
+
* `resolveCheckRelation`), so this model must be applied to the project for
|
|
16
|
+
* checks to resolve; with nothing blocked, `use` resolves identically to a bare
|
|
17
|
+
* `users` existence check, so grants alone allow.
|
|
18
|
+
*
|
|
19
|
+
* ## Naming conventions
|
|
20
|
+
*
|
|
21
|
+
* Every name here follows Ory Permissions' documented conventions
|
|
22
|
+
* (https://www.ory.com/docs/keto/concepts/namespaces#naming-conventions):
|
|
23
|
+
*
|
|
24
|
+
* - **Namespaces** are TypeScript classes named after the **singular** form of
|
|
25
|
+
* the type they describe, in UpperCamelCase — `AgentTool`, `ShellTool`,
|
|
26
|
+
* `Delegation`, `PermissionMode`, `User`, `Agent`, `SubAgent`, `Session`.
|
|
27
|
+
* - **Relations** are **plural** nouns naming the set of subjects on the far end
|
|
28
|
+
* of the edge, so each reads as an English sentence — `User:bob is in users of
|
|
29
|
+
* AgentTool:Bash`, `Agent:abc is in credentials of Delegation:agent:<join>`.
|
|
30
|
+
* - **Permits** are verbs, like Keto's own `view` — hence `use` for "may this
|
|
31
|
+
* subject use this tool", which is the question the gate actually asks.
|
|
32
|
+
* - A namespace holds a **homogeneous** type of object. That is why delegation
|
|
33
|
+
* nodes and the posture sentinels are *not* tool objects: `AgentTool` holds
|
|
34
|
+
* only tools, `Delegation` only delegation nodes, `PermissionMode` only the
|
|
35
|
+
* posture anchors. A single namespace holding all three is the case the
|
|
36
|
+
* convention doc calls out as incorrect, and it forced one class to carry a
|
|
37
|
+
* grab bag of unrelated relations.
|
|
38
|
+
*
|
|
39
|
+
* A relation and a permit cannot share a name in OPL — which is exactly why the
|
|
40
|
+
* grant relation is the plural `users` and the permit the singular verb `use`.
|
|
41
|
+
*/
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.NODE_REFERENCE_NAMESPACES = exports.PRINCIPAL_NAMESPACES = exports.OPL_IMPORT_SYMBOLS = exports.OPL_IMPORT_MODULE = exports.PERMIT_USE = exports.PROJECT_POSTURE_OBJECT = exports.PERMISSION_MODE_OBJECT = exports.PERMISSION_MODE_NAMESPACE = exports.RELATION_OPTED_OUT_SUBJECTS = exports.AUTO_ENROLL_OBJECT = exports.ENROLLMENT_NAMESPACE = exports.RELATION_MEMBERS = exports.SUBAGENT_TYPE_NAMESPACE = exports.AGENT_TYPE_NAMESPACE = exports.AGENT_ROLE_NAMESPACE = exports.SUBAGENT_NODE_NAMESPACE = exports.AGENT_NODE_NAMESPACE = exports.DELEGATION_NAMESPACE = exports.DEFAULT_SHELL_NAMESPACE = exports.DEFAULT_NAMESPACE = exports.RELATION_ENFORCED_SUBJECTS = exports.RELATION_CREDENTIALS = exports.RELATION_BLOCKED_SUBJECTS = exports.RELATION_DELEGATES = exports.RELATION_USERS = void 0;
|
|
44
|
+
exports.renderOplImport = renderOplImport;
|
|
45
|
+
exports.renderPrincipalClass = renderPrincipalClass;
|
|
46
|
+
exports.renderToolNamespaceClass = renderToolNamespaceClass;
|
|
47
|
+
exports.renderDelegationNamespaceClass = renderDelegationNamespaceClass;
|
|
48
|
+
exports.renderAgentRoleNamespaceClass = renderAgentRoleNamespaceClass;
|
|
49
|
+
exports.renderAgentTypeNamespaceClass = renderAgentTypeNamespaceClass;
|
|
50
|
+
exports.renderEnrollmentNamespaceClass = renderEnrollmentNamespaceClass;
|
|
51
|
+
exports.renderPermissionModeNamespaceClass = renderPermissionModeNamespaceClass;
|
|
52
|
+
exports.buildAgentSecurityOpl = buildAgentSecurityOpl;
|
|
53
|
+
const subject_js_1 = require("./subject.js");
|
|
54
|
+
/**
|
|
55
|
+
* The relation that grants a subject use of a tool object — the set of subjects
|
|
56
|
+
* that may use it. Written in the Ory Console (Agent Security); the plugin only
|
|
57
|
+
* ever reads it. Reads as `User:bob is in users of AgentTool:Bash`.
|
|
58
|
+
*/
|
|
59
|
+
exports.RELATION_USERS = "users";
|
|
60
|
+
/**
|
|
61
|
+
* The relation that records a delegation edge on a {@link DELEGATION_NAMESPACE}
|
|
62
|
+
* node (`user→agent`, `agent→subagent`) — the set of subjects that delegated to
|
|
63
|
+
* it. Written by the agent-security broker, never by the runtime; declared here
|
|
64
|
+
* so the local Keto mount (which loads this OPL) accepts the tuples.
|
|
65
|
+
*/
|
|
66
|
+
exports.RELATION_DELEGATES = "delegates";
|
|
67
|
+
/**
|
|
68
|
+
* The relation that explicitly blocks subjects from a tool object
|
|
69
|
+
* (deny-override). A participle has no natural plural, so the relation names the
|
|
70
|
+
* set it holds: `User:bob is in blockedSubjects of AgentTool:curl`.
|
|
71
|
+
*/
|
|
72
|
+
exports.RELATION_BLOCKED_SUBJECTS = "blockedSubjects";
|
|
73
|
+
/**
|
|
74
|
+
* The relation recording which OAuth2 clients a delegation node ran as:
|
|
75
|
+
* `Delegation:agent:<join>#credentials@(Agent:<clientId>)`. Written by the
|
|
76
|
+
* broker, never by the runtime, and never checked — a delegation node is keyed
|
|
77
|
+
* on (identity, harness, host) so that it survives credential rotation, which
|
|
78
|
+
* means the node alone cannot say which credential acted and two clients for one
|
|
79
|
+
* triple collapse onto it. This edge carries that missing axis, for audit and so
|
|
80
|
+
* a reader can join a node to its client exactly rather than by inference.
|
|
81
|
+
*/
|
|
82
|
+
exports.RELATION_CREDENTIALS = "credentials";
|
|
83
|
+
/**
|
|
84
|
+
* The relation holding the subjects that are in **enforce** mode. Read (never
|
|
85
|
+
* written by the runtime) via a `checkPermission` on the
|
|
86
|
+
* {@link PERMISSION_MODE_OBJECT} anchor: an admin grants
|
|
87
|
+
* `PermissionMode:mode#enforcedSubjects@<subject>` (directly, or to a
|
|
88
|
+
* subject-set / group for a project-wide flip) to promote that principal from
|
|
89
|
+
* the default `observe` posture to `enforce`. Absence ⇒ `observe`. Named for the
|
|
90
|
+
* set it holds, since `enforce` is a verb and has no plural noun form.
|
|
91
|
+
*/
|
|
92
|
+
exports.RELATION_ENFORCED_SUBJECTS = "enforcedSubjects";
|
|
93
|
+
/**
|
|
94
|
+
* Default permission namespace / OPL class name for harness tool objects
|
|
95
|
+
* (`AgentTool:Bash`). Singular, because the namespace describes *one tool*, and
|
|
96
|
+
* an object in it is one. Mirrors `ORY_PERMISSION_NAMESPACE`.
|
|
97
|
+
*/
|
|
98
|
+
exports.DEFAULT_NAMESPACE = "AgentTool";
|
|
99
|
+
/**
|
|
100
|
+
* Default Keto namespace for decomposed shell-command sub-tools (issue #76) —
|
|
101
|
+
* one object per program/builtin word (`ShellTool:curl`). Rendered with the same
|
|
102
|
+
* grant/block model as {@link DEFAULT_NAMESPACE}, so an explicit
|
|
103
|
+
* `ShellTool:curl#blockedSubjects` overrides a `users` grant. Mirrors
|
|
104
|
+
* `resolveShellCommandNamespace()` in tool-catalog.ts.
|
|
105
|
+
*/
|
|
106
|
+
exports.DEFAULT_SHELL_NAMESPACE = "ShellTool";
|
|
107
|
+
/**
|
|
108
|
+
* Namespace for delegation nodes — the current-state graph of who delegated to
|
|
109
|
+
* whom (`Delegation:agent:<join>`, `Delegation:subagent:<join>|<type>`). Its own
|
|
110
|
+
* namespace because a delegation node is not a tool: mixing the two put
|
|
111
|
+
* heterogeneous objects in one namespace and made the tool class carry
|
|
112
|
+
* delegation relations that no tool object ever uses. The broker owns both the
|
|
113
|
+
* objects and the tuples; the plugin treats a node id as opaque.
|
|
114
|
+
*/
|
|
115
|
+
exports.DELEGATION_NAMESPACE = "Delegation";
|
|
116
|
+
/**
|
|
117
|
+
* Namespaces for **references to** delegation nodes — the parent pointer on a
|
|
118
|
+
* delegation edge (issue #225).
|
|
119
|
+
*
|
|
120
|
+
* `Agent` and `SubAgent` name a *principal identity*: an OAuth2 client that
|
|
121
|
+
* authenticates, and the subject an admin grants or blocks. A delegation edge's
|
|
122
|
+
* `delegates` subject is a different kind of thing — a pointer at another node
|
|
123
|
+
* in the graph, keyed by `<identity>|<harness>|<host>|<session>`. Both were
|
|
124
|
+
* addressed under `Agent` / `SubAgent`, so one namespace carried two meanings:
|
|
125
|
+
*
|
|
126
|
+
* Agent:<clientId> a principal identity
|
|
127
|
+
* Agent:<identity>|<harness>|<host>|<session> a graph-node reference
|
|
128
|
+
*
|
|
129
|
+
* Nothing written today is ambiguous, because a Hydra client id is a UUID and a
|
|
130
|
+
* join key always contains separators — but that disjointness is a property of
|
|
131
|
+
* the *data*, not of the model, and it is reachable-breakable through
|
|
132
|
+
* `ORY_AGENT_SUBJECT_ID` (guarded separately in #241). The costlier problem is
|
|
133
|
+
* silent: an admin, or a Console UI, that reads a node id off the delegation
|
|
134
|
+
* graph and writes it as a grant subject produces a tuple that is accepted,
|
|
135
|
+
* stored, and never matches any check — the same failure the SubjectSet-vs-
|
|
136
|
+
* SubjectID invariant exists to prevent, one level up. That surface is four
|
|
137
|
+
* relations wide (`users`, `blockedSubjects`, `members`, `enforcedSubjects`).
|
|
138
|
+
*
|
|
139
|
+
* Splitting the two meanings apart makes the wrong-form grant name a namespace
|
|
140
|
+
* that has no `users` relation at all, rather than looking plausible. It also
|
|
141
|
+
* lets the broker's downward walk use the right namespace per level instead of
|
|
142
|
+
* guessing `Agent` for every level — the latent inconsistency that would become
|
|
143
|
+
* a real bug the moment nested sub-agents ship.
|
|
144
|
+
*/
|
|
145
|
+
exports.AGENT_NODE_NAMESPACE = "AgentNode";
|
|
146
|
+
/** Sub-agent counterpart of {@link AGENT_NODE_NAMESPACE}. */
|
|
147
|
+
exports.SUBAGENT_NODE_NAMESPACE = "SubAgentNode";
|
|
148
|
+
/**
|
|
149
|
+
* Namespace for the shared role a project grants tools to, rather than granting
|
|
150
|
+
* every identity directly (`AgentRole:agent-security-users#members@(User:<id>)`,
|
|
151
|
+
* with each tool granted to `(AgentRole:agent-security-users#members)`). Written
|
|
152
|
+
* by the Ory Console and the Agent Security broker's enrollment; the plugin only
|
|
153
|
+
* ever resolves it as part of the `use` permit.
|
|
154
|
+
*
|
|
155
|
+
* Its own namespace because a role is not a tool. That is also what makes **one**
|
|
156
|
+
* role tuple enough: while the role was a tool object, a membership had to be
|
|
157
|
+
* written once per tool namespace (Keto matches a subject-set exactly, and the
|
|
158
|
+
* role object's namespace had to be the same as the granting object's), so the
|
|
159
|
+
* same role existed twice and could drift.
|
|
160
|
+
*/
|
|
161
|
+
exports.AGENT_ROLE_NAMESPACE = "AgentRole";
|
|
162
|
+
/** Group of registered agent credentials sharing a harness key. */
|
|
163
|
+
exports.AGENT_TYPE_NAMESPACE = "AgentType";
|
|
164
|
+
/** Group of registered sub-agent credentials sharing a type name. */
|
|
165
|
+
exports.SUBAGENT_TYPE_NAMESPACE = "SubAgentType";
|
|
166
|
+
/** The relation naming a role's members. Reads as `User:bob is in members of AgentRole:<role>`. */
|
|
167
|
+
exports.RELATION_MEMBERS = "members";
|
|
168
|
+
/**
|
|
169
|
+
* Namespace for Agent Security enrollment settings — currently whether a newly
|
|
170
|
+
* connected agent's identity is auto-enrolled into the shared role. Stored as an
|
|
171
|
+
* **opt-out** (`Enrollment:autoEnroll#optedOutSubjects@(Enrollment:project#optedOutSubjects)`)
|
|
172
|
+
* so absence means on, which is what a project provisioned before the setting
|
|
173
|
+
* existed reads as. Written and read by the Console and the broker.
|
|
174
|
+
*/
|
|
175
|
+
exports.ENROLLMENT_NAMESPACE = "Enrollment";
|
|
176
|
+
/** The object the auto-enroll setting hangs off. */
|
|
177
|
+
exports.AUTO_ENROLL_OBJECT = "autoEnroll";
|
|
178
|
+
/** The relation holding the subjects that opted out of a setting. */
|
|
179
|
+
exports.RELATION_OPTED_OUT_SUBJECTS = "optedOutSubjects";
|
|
180
|
+
/**
|
|
181
|
+
* Namespace for the server-read deny posture. Its own namespace for the same
|
|
182
|
+
* reason as {@link DELEGATION_NAMESPACE}: the posture anchor is not a tool, and
|
|
183
|
+
* once it stops sharing a namespace with tool names it no longer needs a
|
|
184
|
+
* collision-proof sentinel spelling either — hence the plain
|
|
185
|
+
* {@link PERMISSION_MODE_OBJECT} / {@link PROJECT_POSTURE_OBJECT} object ids
|
|
186
|
+
* rather than the double-underscore guards an earlier release used.
|
|
187
|
+
*/
|
|
188
|
+
exports.PERMISSION_MODE_NAMESPACE = "PermissionMode";
|
|
189
|
+
/**
|
|
190
|
+
* The object an enforce-mode grant hangs off. The permission mode is resolved as
|
|
191
|
+
* `checkPermission(PermissionMode:mode#enforcedSubjects@<subject>)`.
|
|
192
|
+
*/
|
|
193
|
+
exports.PERMISSION_MODE_OBJECT = "mode";
|
|
194
|
+
/**
|
|
195
|
+
* Object standing in for **every principal on the project**, used as the subject
|
|
196
|
+
* of a project-wide posture grant:
|
|
197
|
+
*
|
|
198
|
+
* PermissionMode:mode#enforcedSubjects@(PermissionMode:project#enforcedSubjects)
|
|
199
|
+
*
|
|
200
|
+
* Keto has no wildcard subject, and a per-principal grant cannot cover a
|
|
201
|
+
* principal that does not exist yet — so an agent connecting after an admin
|
|
202
|
+
* turned on enforce would resolve `observe` and silently escape enforcement
|
|
203
|
+
* until someone re-applied the grant for it. Checking this fixed sentinel first
|
|
204
|
+
* makes the posture a property of the project: one relation governs every
|
|
205
|
+
* principal, present and future. Per-principal grants remain meaningful as
|
|
206
|
+
* exceptions (enforce one user while the project is still observing).
|
|
207
|
+
*/
|
|
208
|
+
exports.PROJECT_POSTURE_OBJECT = "project";
|
|
209
|
+
/**
|
|
210
|
+
* The permit Argus checks: `users && !blockedSubjects`, evaluated natively by
|
|
211
|
+
* Keto. A verb, as Keto's own `view` is — it names the question the gate asks.
|
|
212
|
+
*/
|
|
213
|
+
exports.PERMIT_USE = "use";
|
|
214
|
+
/** Conventional user namespace used for SubjectSet-addressed users (`User:<id>`). */
|
|
215
|
+
const USER_NAMESPACE = "User";
|
|
216
|
+
/**
|
|
217
|
+
* The module OPL sources import their type symbols from. Keto's parser
|
|
218
|
+
* recognizes this name (and the equivalent `@ory/permission-namespace-types`)
|
|
219
|
+
* and strips the import — no npm dependency is pulled at runtime.
|
|
220
|
+
*/
|
|
221
|
+
exports.OPL_IMPORT_MODULE = "@ory/keto-namespace-types";
|
|
222
|
+
/**
|
|
223
|
+
* Every type symbol the rendered OPL references, and therefore must import:
|
|
224
|
+
* `Namespace` (every class implements it), `SubjectSet` (the relation unions
|
|
225
|
+
* allow set expansion), and `Context` (the `use` permit is typed
|
|
226
|
+
* `(ctx: Context)`). This is the canonical set — any code that assembles or
|
|
227
|
+
* merges the OPL imports exactly these.
|
|
228
|
+
*/
|
|
229
|
+
exports.OPL_IMPORT_SYMBOLS = ["Namespace", "SubjectSet", "Context"];
|
|
230
|
+
/**
|
|
231
|
+
* The principal namespaces every subject is addressed under (SubjectSets):
|
|
232
|
+
* `User`, `Agent`, `SubAgent`, and the `Session` fallback. The object
|
|
233
|
+
* namespaces' relations are typed by them, so they must be defined for checks to
|
|
234
|
+
* resolve rather than `NotFound`.
|
|
235
|
+
*
|
|
236
|
+
* These are **identities** — things that authenticate and that an admin can
|
|
237
|
+
* grant or block. Graph-node references are a separate kind and live in
|
|
238
|
+
* {@link NODE_REFERENCE_NAMESPACES}; keeping the two lists apart is what stops a
|
|
239
|
+
* node id from being written where an identity belongs (#225).
|
|
240
|
+
*/
|
|
241
|
+
exports.PRINCIPAL_NAMESPACES = [
|
|
242
|
+
USER_NAMESPACE,
|
|
243
|
+
subject_js_1.AGENT_NAMESPACE,
|
|
244
|
+
subject_js_1.SUBAGENT_NAMESPACE,
|
|
245
|
+
subject_js_1.SESSION_NAMESPACE,
|
|
246
|
+
];
|
|
247
|
+
/**
|
|
248
|
+
* Namespaces holding references to delegation-graph nodes. Declared so the
|
|
249
|
+
* `delegates` relation that is typed by them resolves, and deliberately *not*
|
|
250
|
+
* part of {@link PRINCIPAL_NAMESPACES}: a node reference is never a grant, block,
|
|
251
|
+
* role-membership, or posture subject.
|
|
252
|
+
*/
|
|
253
|
+
exports.NODE_REFERENCE_NAMESPACES = [
|
|
254
|
+
exports.AGENT_NODE_NAMESPACE,
|
|
255
|
+
exports.SUBAGENT_NODE_NAMESPACE,
|
|
256
|
+
];
|
|
257
|
+
/** Render the canonical import line for a from-scratch OPL file. */
|
|
258
|
+
function renderOplImport() {
|
|
259
|
+
return `import { ${exports.OPL_IMPORT_SYMBOLS.join(", ")} } from "${exports.OPL_IMPORT_MODULE}"`;
|
|
260
|
+
}
|
|
261
|
+
/** Render a principal-namespace class (an empty `implements Namespace`). */
|
|
262
|
+
function renderPrincipalClass(name) {
|
|
263
|
+
return `class ${name} implements Namespace {}`;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Render a tool-namespace class body: the `users` grant, the `blockedSubjects`
|
|
267
|
+
* deny-override, and the `use` permit (`users && !blockedSubjects`) Argus
|
|
268
|
+
* checks. The single definition of that class, used for both tool namespaces.
|
|
269
|
+
*/
|
|
270
|
+
function renderToolNamespaceClass(namespace = exports.DEFAULT_NAMESPACE) {
|
|
271
|
+
return `class ${namespace} implements Namespace {
|
|
272
|
+
related: {
|
|
273
|
+
// Machine principals are grantable in their own right: \`${subject_js_1.AGENT_NAMESPACE}:<clientId>\` is
|
|
274
|
+
// one session's registered agent credential and \`${subject_js_1.SUBAGENT_NAMESPACE}:<clientId>\` one
|
|
275
|
+
// typed sub-agent credential in that session. Their narrower session- and spawn-scoped forms
|
|
276
|
+
// (\`${subject_js_1.AGENT_NAMESPACE}:<clientId>|<session>\`, \`${subject_js_1.SUBAGENT_NAMESPACE}:<clientId>|<session>|<type>\`) are
|
|
277
|
+
// members of the same namespaces, which is what lets a block name one run.
|
|
278
|
+
// A grant may also name the shared role, so one membership covers every
|
|
279
|
+
// tool in every tool namespace: \`@(${exports.AGENT_ROLE_NAMESPACE}:<role>#${exports.RELATION_MEMBERS})\`.
|
|
280
|
+
${exports.RELATION_USERS}: (${USER_NAMESPACE} | ${subject_js_1.SESSION_NAMESPACE} | ${subject_js_1.AGENT_NAMESPACE} | ${subject_js_1.SUBAGENT_NAMESPACE} | SubjectSet<${exports.AGENT_ROLE_NAMESPACE}, "${exports.RELATION_MEMBERS}"> | SubjectSet<${namespace}, "${exports.RELATION_USERS}">)[]
|
|
281
|
+
${exports.RELATION_BLOCKED_SUBJECTS}: (${USER_NAMESPACE} | ${subject_js_1.SESSION_NAMESPACE} | ${subject_js_1.AGENT_NAMESPACE} | ${subject_js_1.SUBAGENT_NAMESPACE} | SubjectSet<${exports.AGENT_ROLE_NAMESPACE}, "${exports.RELATION_MEMBERS}"> | SubjectSet<${namespace}, "${exports.RELATION_BLOCKED_SUBJECTS}">)[]
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
permits = {
|
|
285
|
+
// Deny-override: any matching \`${exports.RELATION_BLOCKED_SUBJECTS}\` relation beats a
|
|
286
|
+
// \`${exports.RELATION_USERS}\` grant, regardless of how the grant was reached (direct or
|
|
287
|
+
// via a set).
|
|
288
|
+
${exports.PERMIT_USE}: (ctx: Context): boolean =>
|
|
289
|
+
this.related.${exports.RELATION_USERS}.includes(ctx.subject) &&
|
|
290
|
+
!this.related.${exports.RELATION_BLOCKED_SUBJECTS}.includes(ctx.subject),
|
|
291
|
+
}
|
|
292
|
+
}`;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Render the delegation-node class: who delegated to this node, and which OAuth2
|
|
296
|
+
* clients it ran as. Nothing is ever checked here — the graph is an audit trail —
|
|
297
|
+
* but the relations must be declared for the broker's writes to be accepted.
|
|
298
|
+
*/
|
|
299
|
+
function renderDelegationNamespaceClass(namespace = exports.DELEGATION_NAMESPACE) {
|
|
300
|
+
return `class ${namespace} implements Namespace {
|
|
301
|
+
related: {
|
|
302
|
+
// A delegation edge's subject is whoever delegated. For a user that is the
|
|
303
|
+
// identity itself (${USER_NAMESPACE}:<id>); for a machine it is a *reference to the
|
|
304
|
+
// delegating node* — \`${exports.AGENT_NODE_NAMESPACE}:<identity>|<harness>|<host>|<session>\`, not the
|
|
305
|
+
// OAuth2 client id. Those are different kinds of thing and no longer share a
|
|
306
|
+
// namespace with the grant/block identities (#225), so a node id that ends up
|
|
307
|
+
// written as a grant subject is visibly the wrong kind rather than being
|
|
308
|
+
// spelled exactly like a correct one. (Keto still stores such a tuple — it
|
|
309
|
+
// does not type-check subjects on write — it just never matches anything.)
|
|
310
|
+
${exports.RELATION_DELEGATES}: (${USER_NAMESPACE} | ${exports.AGENT_NODE_NAMESPACE} | ${exports.SUBAGENT_NODE_NAMESPACE})[]
|
|
311
|
+
// Which OAuth2 clients this node ran as. Recorded for audit, never checked —
|
|
312
|
+
// the node key survives credential rotation, so this is the only place the
|
|
313
|
+
// credential that actually acted is written down.
|
|
314
|
+
${exports.RELATION_CREDENTIALS}: (${subject_js_1.AGENT_NAMESPACE} | ${subject_js_1.SUBAGENT_NAMESPACE})[]
|
|
315
|
+
}
|
|
316
|
+
}`;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Render the role class: the members of a shared role a project grants tools to.
|
|
320
|
+
* One class, one relation — a role is a group of subjects and nothing else.
|
|
321
|
+
*/
|
|
322
|
+
function renderAgentRoleNamespaceClass(namespace = exports.AGENT_ROLE_NAMESPACE) {
|
|
323
|
+
return `class ${namespace} implements Namespace {
|
|
324
|
+
related: {
|
|
325
|
+
// The subjects that belong to the role. A tool grant names
|
|
326
|
+
// \`(${namespace}:<role>#${exports.RELATION_MEMBERS})\` as its subject, so adding a member grants
|
|
327
|
+
// every tool the role holds, in either tool namespace, from one relation.
|
|
328
|
+
${exports.RELATION_MEMBERS}: (${USER_NAMESPACE} | ${subject_js_1.AGENT_NAMESPACE} | ${subject_js_1.SUBAGENT_NAMESPACE} | SubjectSet<${namespace}, "${exports.RELATION_MEMBERS}">)[]
|
|
329
|
+
}
|
|
330
|
+
}`;
|
|
331
|
+
}
|
|
332
|
+
/** Render a harness/sub-agent type group whose members inherit posture. */
|
|
333
|
+
function renderAgentTypeNamespaceClass(namespace, memberNamespace) {
|
|
334
|
+
return `class ${namespace} implements Namespace {
|
|
335
|
+
related: {
|
|
336
|
+
${exports.RELATION_MEMBERS}: (${memberNamespace} | SubjectSet<${namespace}, "${exports.RELATION_MEMBERS}">)[]
|
|
337
|
+
}
|
|
338
|
+
}`;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Render the enrollment-settings class: which subjects opted out of a setting.
|
|
342
|
+
* An opt-out rather than an opt-in, so absence reads as "on".
|
|
343
|
+
*/
|
|
344
|
+
function renderEnrollmentNamespaceClass(namespace = exports.ENROLLMENT_NAMESPACE) {
|
|
345
|
+
return `class ${namespace} implements Namespace {
|
|
346
|
+
related: {
|
|
347
|
+
// Auto-enrollment of a newly connected agent's identity into the shared role
|
|
348
|
+
// is on unless opted out, so the setting is stored as an opt-out on the
|
|
349
|
+
// \`${exports.AUTO_ENROLL_OBJECT}\` object. Absence means on — which is also how a project
|
|
350
|
+
// provisioned before the setting existed reads.
|
|
351
|
+
${exports.RELATION_OPTED_OUT_SUBJECTS}: (${USER_NAMESPACE} | SubjectSet<${namespace}, "${exports.RELATION_OPTED_OUT_SUBJECTS}">)[]
|
|
352
|
+
}
|
|
353
|
+
}`;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Render the permission-mode class: the set of subjects an admin has promoted
|
|
357
|
+
* from `observe` to `enforce`. One relation, read by every gate.
|
|
358
|
+
*/
|
|
359
|
+
function renderPermissionModeNamespaceClass(namespace = exports.PERMISSION_MODE_NAMESPACE) {
|
|
360
|
+
return `class ${namespace} implements Namespace {
|
|
361
|
+
related: {
|
|
362
|
+
// An admin grants \`${exports.RELATION_ENFORCED_SUBJECTS}\` on the \`${exports.PERMISSION_MODE_OBJECT}\` object to
|
|
363
|
+
// promote a subject (or a whole group, via a SubjectSet) from the default
|
|
364
|
+
// \`observe\` posture to \`enforce\`. The \`${exports.PROJECT_POSTURE_OBJECT}\` sentinel subject-set is
|
|
365
|
+
// how a posture is set for the whole project, including principals that do
|
|
366
|
+
// not exist yet. Sub-agents are promotable in their own right.
|
|
367
|
+
${exports.RELATION_ENFORCED_SUBJECTS}: (${USER_NAMESPACE} | ${subject_js_1.SESSION_NAMESPACE} | ${subject_js_1.AGENT_NAMESPACE} | ${subject_js_1.SUBAGENT_NAMESPACE} | SubjectSet<${exports.AGENT_TYPE_NAMESPACE}, "${exports.RELATION_MEMBERS}"> | SubjectSet<${exports.SUBAGENT_TYPE_NAMESPACE}, "${exports.RELATION_MEMBERS}"> | SubjectSet<${namespace}, "${exports.RELATION_ENFORCED_SUBJECTS}">)[]
|
|
368
|
+
}
|
|
369
|
+
}`;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Render the complete OPL namespace-definition file for the Agent Security
|
|
373
|
+
* model.
|
|
374
|
+
*
|
|
375
|
+
* This is the model an Ory project must have for Agent Security checks to
|
|
376
|
+
* resolve. On a hosted project it is applied in the Ory Console (Agent
|
|
377
|
+
* Security) — the plugin never pushes it. This renderer exists so the **local
|
|
378
|
+
* dev stack** can mount the identical definition into its own Keto config,
|
|
379
|
+
* keeping local and hosted on one definition, and so the model can be printed
|
|
380
|
+
* for reference.
|
|
381
|
+
*
|
|
382
|
+
* `namespace` is the tool namespace (OPL class name); defaults to
|
|
383
|
+
* {@link DEFAULT_NAMESPACE}. Operators who override `ORY_PERMISSION_NAMESPACE`
|
|
384
|
+
* must provision the schema under the same name so the class the checks address
|
|
385
|
+
* exists. The `Delegation` and `PermissionMode` namespaces are not
|
|
386
|
+
* operator-configurable — they hold project-wide state, not per-deployment tool
|
|
387
|
+
* objects.
|
|
388
|
+
*
|
|
389
|
+
* The output is the TypeScript-flavored OPL source Keto parses (the import is
|
|
390
|
+
* recognized and stripped by Keto's parser — no npm dependency is pulled at
|
|
391
|
+
* runtime). It is written verbatim into the local stack's keto config mount.
|
|
392
|
+
*/
|
|
393
|
+
function buildAgentSecurityOpl(namespace = exports.DEFAULT_NAMESPACE, shellNamespace = exports.DEFAULT_SHELL_NAMESPACE) {
|
|
394
|
+
return [
|
|
395
|
+
renderOplImport(),
|
|
396
|
+
"",
|
|
397
|
+
"// Principal namespaces. Every principal — user, agent, sub-agent, and the",
|
|
398
|
+
`// \`${subject_js_1.SESSION_NAMESPACE}:<id>\` fallback subject — is addressed as a SubjectSet`,
|
|
399
|
+
`// (\`${USER_NAMESPACE}:<id>\`, \`${subject_js_1.AGENT_NAMESPACE}:<id>\`, …). They must exist so the object`,
|
|
400
|
+
"// namespaces' relations, which are typed by them, resolve.",
|
|
401
|
+
...exports.PRINCIPAL_NAMESPACES.map(renderPrincipalClass),
|
|
402
|
+
"",
|
|
403
|
+
"// Delegation-graph node references. Distinct from the principal namespaces",
|
|
404
|
+
"// above because a node reference is not an identity: it is a pointer at a",
|
|
405
|
+
`// node keyed \`<identity>|<harness>|<host>|<session>\`, and it is only ever the`,
|
|
406
|
+
`// subject of \`${exports.RELATION_DELEGATES}\`. Keeping it out of \`${subject_js_1.AGENT_NAMESPACE}\` / \`${subject_js_1.SUBAGENT_NAMESPACE}\` means a`,
|
|
407
|
+
"// node id written as a grant, block, role, or posture subject names a class",
|
|
408
|
+
"// that has no such relation, rather than storing a tuple that never matches.",
|
|
409
|
+
...exports.NODE_REFERENCE_NAMESPACES.map(renderPrincipalClass),
|
|
410
|
+
"",
|
|
411
|
+
`// Harness tool objects (\`${namespace}:Bash\`). \`${exports.RELATION_USERS}\` is the set of subjects`,
|
|
412
|
+
`// granted the tool; \`${exports.RELATION_BLOCKED_SUBJECTS}\` is an explicit deny-override. The`,
|
|
413
|
+
`// \`${exports.PERMIT_USE}\` permit is the effective decision Argus checks: granted AND not`,
|
|
414
|
+
"// blocked.",
|
|
415
|
+
renderToolNamespaceClass(namespace),
|
|
416
|
+
"",
|
|
417
|
+
"// Shell command sub-tools (issue #76): each program/builtin word a shell",
|
|
418
|
+
`// command runs is checked as \`${shellNamespace}:<word>#${exports.PERMIT_USE}\`, so a blocked`,
|
|
419
|
+
'// binary (e.g. curl) can\'t be reached through `bash -c "curl …"`. Same',
|
|
420
|
+
"// grant / block / use model as the tool namespace above.",
|
|
421
|
+
renderToolNamespaceClass(shellNamespace),
|
|
422
|
+
"",
|
|
423
|
+
"// The shared role a project grants tools to, so an admin adds a member",
|
|
424
|
+
"// instead of re-granting every tool per identity.",
|
|
425
|
+
renderAgentRoleNamespaceClass(),
|
|
426
|
+
"",
|
|
427
|
+
"// Delegation nodes: the current-state graph of who delegated to whom, written",
|
|
428
|
+
"// by the agent-security broker and read by the Console. Audit only — no",
|
|
429
|
+
"// permission check resolves against it.",
|
|
430
|
+
renderDelegationNamespaceClass(),
|
|
431
|
+
"",
|
|
432
|
+
"// Registered credential groups used to apply posture by harness or sub-agent type.",
|
|
433
|
+
renderAgentTypeNamespaceClass(exports.AGENT_TYPE_NAMESPACE, subject_js_1.AGENT_NAMESPACE),
|
|
434
|
+
"",
|
|
435
|
+
renderAgentTypeNamespaceClass(exports.SUBAGENT_TYPE_NAMESPACE, subject_js_1.SUBAGENT_NAMESPACE),
|
|
436
|
+
"",
|
|
437
|
+
"// Server-read deny posture: which subjects are in `enforce` rather than the",
|
|
438
|
+
"// default `observe`. Set in the Ory Console, read by every gate.",
|
|
439
|
+
renderPermissionModeNamespaceClass(),
|
|
440
|
+
"",
|
|
441
|
+
"// Agent Security enrollment settings, stored as opt-outs so absence reads as",
|
|
442
|
+
"// the default (on). Written and read by the Console and the broker.",
|
|
443
|
+
renderEnrollmentNamespaceClass(),
|
|
444
|
+
"",
|
|
445
|
+
].join("\n");
|
|
446
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-read permission mode.
|
|
3
|
+
*
|
|
4
|
+
* `observe` vs `enforce` is no longer a local, per-machine setting — it is a
|
|
5
|
+
* **permission the plugin reads from Keto** before gating a tool call, so an
|
|
6
|
+
* admin controls the deny posture centrally from the Ory project (Ory Console /
|
|
7
|
+
* Agent Security), and every session inherits it. There is no local override
|
|
8
|
+
* and no `ORY_PERMISSION_MODE` env var.
|
|
9
|
+
*
|
|
10
|
+
* The mode lives in its own `PermissionMode` namespace — it is not a tool, so it
|
|
11
|
+
* is not a tool object (see the naming-conventions note in `opl.ts`). It is
|
|
12
|
+
* resolved by `checkPermission` against the `mode` anchor, at two scopes:
|
|
13
|
+
*
|
|
14
|
+
* project: PermissionMode:mode#enforcedSubjects@(PermissionMode:project#enforcedSubjects)
|
|
15
|
+
* applicable: PermissionMode:mode#enforcedSubjects@<identity|agent|subagent>
|
|
16
|
+
* allowed ⇒ enforce denied ⇒ observe
|
|
17
|
+
*
|
|
18
|
+
* The **project** grant is checked first and is the posture an admin normally
|
|
19
|
+
* sets: one tuple governs every principal, including ones that do not exist
|
|
20
|
+
* yet. That matters because a per-principal grant cannot cover a future
|
|
21
|
+
* principal — before the project scope existed, an agent connecting after an
|
|
22
|
+
* admin turned on enforce resolved `observe` and silently escaped enforcement
|
|
23
|
+
* until someone re-applied the grant for it. A **per-principal** grant remains
|
|
24
|
+
* meaningful as an exception: enforce one identity, agent harness, or sub-agent
|
|
25
|
+
* type while the project still observes. Type grants are inherited through the
|
|
26
|
+
* server-managed AgentType/SubAgentType membership relations.
|
|
27
|
+
* Neither scope can be set by the runtime — the plugin only ever reads, riding
|
|
28
|
+
* its own OAuth2 access token like every other Keto read.
|
|
29
|
+
*
|
|
30
|
+
* Resolution precedence, applied by {@link resolvePermissionMode}:
|
|
31
|
+
*
|
|
32
|
+
* 1. **In-memory TTL cache** (per scope) — avoids a Keto round-trip on
|
|
33
|
+
* literally every tool call while still re-reading the server every `ttlMs()`.
|
|
34
|
+
* The project scope caches under one key shared by every subject, so the
|
|
35
|
+
* common "whole project enforced" case costs a single read per TTL window.
|
|
36
|
+
* 2. **Server check** — project scope, then identity and acting machine scopes
|
|
37
|
+
* only if the project is not enforcing. On a clean result, refresh the in-memory cache
|
|
38
|
+
* and return it (`source: "server"`).
|
|
39
|
+
* 3. **Persistent cache** — when the server is unreachable, fall back to the
|
|
40
|
+
* last value read from the server, persisted in `config.json`
|
|
41
|
+
* (`source: "cache"`).
|
|
42
|
+
* 4. **`observe`** — nothing was ever cached (`source: "default"`).
|
|
43
|
+
*
|
|
44
|
+
* The persistent cache is written by {@link warmPermissionModeCache} at session
|
|
45
|
+
* start and when a gate first discovers a new acting-machine scope. It only
|
|
46
|
+
* writes when a cached mode changes, so normal per-tool checks do not churn the
|
|
47
|
+
* shared config while child-only posture still survives subprocess boundaries.
|
|
48
|
+
*/
|
|
49
|
+
import type { OryAgentClient } from "./client.js";
|
|
50
|
+
import { type PermissionMode } from "./config.js";
|
|
51
|
+
import type { PermissionCheck } from "./types.js";
|
|
52
|
+
/** Where {@link resolvePermissionMode} sourced the value it returned. */
|
|
53
|
+
export type PermissionModeSource = "server" | "cache" | "default";
|
|
54
|
+
/** The subject a mode check is evaluated for — the same shape as a tool check. */
|
|
55
|
+
export type ModeSubject = Pick<PermissionCheck, "subjectId" | "subjectSet">;
|
|
56
|
+
export interface ResolvedPermissionMode {
|
|
57
|
+
mode: PermissionMode;
|
|
58
|
+
source: PermissionModeSource;
|
|
59
|
+
}
|
|
60
|
+
export interface AdditionalModeSubject {
|
|
61
|
+
subject: ModeSubject;
|
|
62
|
+
scope: "agent" | "subagent";
|
|
63
|
+
}
|
|
64
|
+
/** Drop all in-memory caches. Test-only (reassigns the WeakMap). */
|
|
65
|
+
export declare function resetPermissionModeCache(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the current permission mode for `subject`. Never throws — a Keto
|
|
68
|
+
* error falls back to the persistent cache, then `observe`. See the module
|
|
69
|
+
* doc for the precedence. Does **not** persist (that is
|
|
70
|
+
* {@link warmPermissionModeCache}'s job); `opts.now` is injectable for tests.
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolvePermissionMode(client: OryAgentClient, subject: ModeSubject, opts?: {
|
|
73
|
+
now?: number;
|
|
74
|
+
additionalSubjects?: AdditionalModeSubject[];
|
|
75
|
+
}): Promise<ResolvedPermissionMode>;
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the mode and, when it came from a live server read, persist it to
|
|
78
|
+
* `config.json` so a subprocess harness's later hook processes (and the
|
|
79
|
+
* synchronous MCP `applyPermissionMode` path) see the current posture, and so a
|
|
80
|
+
* subsequent offline session has a cached value to fall back to. Called once at
|
|
81
|
+
* session start. Best-effort; never throws. Only writes when the value changed,
|
|
82
|
+
* so it doesn't churn the config lockfile.
|
|
83
|
+
*/
|
|
84
|
+
export declare function warmPermissionModeCache(client: OryAgentClient, subject: ModeSubject, opts?: {
|
|
85
|
+
now?: number;
|
|
86
|
+
additionalSubjects?: AdditionalModeSubject[];
|
|
87
|
+
}): Promise<ResolvedPermissionMode>;
|