@ory/argus 0.14.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -46
- package/assets/commands/temporal-up.md +1 -1
- package/assets/skills/auth-setup/SKILL.md +1 -1
- package/assets/skills/local-dev/SKILL.md +17 -7
- package/assets/skills/ory-build-agent/SKILL.md +39 -91
- package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -17
- package/assets/skills/ory-temporal-worker/SKILL.md +31 -33
- package/assets/skills/permissions-onboarding/SKILL.md +131 -104
- package/dist/adapters.d.ts +88 -32
- package/dist/adapters.js +443 -164
- package/dist/agent-auth.d.ts +226 -67
- package/dist/agent-auth.js +951 -205
- package/dist/auth-store.d.ts +37 -2
- package/dist/auth-store.js +37 -3
- package/dist/auth.d.ts +33 -4
- package/dist/auth.js +163 -20
- package/dist/bash-parser.d.ts +98 -0
- package/dist/bash-parser.js +396 -0
- package/dist/branding.d.ts +77 -16
- package/dist/branding.js +93 -23
- package/dist/build-info.json +4 -4
- package/dist/cli-invocation.d.ts +1 -1
- package/dist/cli-invocation.js +2 -1
- package/dist/cli.d.ts +20 -29
- package/dist/cli.js +271 -239
- package/dist/client.d.ts +175 -138
- package/dist/client.js +672 -391
- package/dist/config.d.ts +217 -54
- package/dist/config.js +461 -42
- package/dist/context.d.ts +10 -0
- package/dist/context.js +21 -0
- package/dist/contract-suite.d.ts +3 -5
- package/dist/contract-suite.js +75 -47
- package/dist/denial.d.ts +36 -3
- package/dist/denial.js +79 -10
- package/dist/event-reporter.d.ts +77 -0
- package/dist/event-reporter.js +776 -0
- package/dist/external-registrations-main.d.ts +10 -0
- package/dist/external-registrations-main.js +38 -0
- package/dist/external-registrations.d.ts +79 -0
- package/dist/external-registrations.js +188 -0
- package/dist/help-cli.d.ts +39 -0
- package/dist/help-cli.js +55 -0
- package/dist/hook-timeout.d.ts +64 -0
- package/dist/hook-timeout.js +88 -0
- package/dist/index.d.ts +28 -23
- package/dist/index.js +173 -58
- package/dist/lifecycle.d.ts +3 -3
- package/dist/lifecycle.js +38 -6
- package/dist/local/cli.js +11 -6
- package/dist/local/configs.d.ts +74 -18
- package/dist/local/configs.js +291 -84
- package/dist/local/health.js +7 -7
- package/dist/local/index.d.ts +2 -2
- package/dist/local/index.js +24 -10
- package/dist/local/manager.d.ts +20 -1
- package/dist/local/manager.js +159 -36
- package/dist/local/ports.d.ts +158 -0
- package/dist/local/ports.js +443 -0
- package/dist/local/seed.d.ts +13 -5
- package/dist/local/seed.js +62 -38
- package/dist/logger.d.ts +54 -25
- package/dist/logger.js +329 -63
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +10 -5
- package/dist/mirror-bootstrap.d.ts +48 -0
- package/dist/mirror-bootstrap.js +254 -0
- package/dist/opl.d.ts +289 -0
- package/dist/opl.js +446 -0
- package/dist/permission-mode.d.ts +87 -0
- package/dist/permission-mode.js +307 -0
- package/dist/permissions-cli.d.ts +13 -49
- package/dist/permissions-cli.js +154 -348
- package/dist/permissions.d.ts +148 -38
- package/dist/permissions.js +591 -45
- package/dist/post-install.d.ts +33 -0
- package/dist/post-install.js +127 -0
- package/dist/read-credential.d.ts +65 -0
- package/dist/read-credential.js +86 -0
- package/dist/registry/cli.js +5 -2
- package/dist/registry/config.d.ts +0 -17
- package/dist/registry/config.js +0 -23
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.js +2 -2
- package/dist/registry/manager.d.ts +4 -21
- package/dist/registry/manager.js +21 -37
- package/dist/runtime-credential.d.ts +140 -0
- package/dist/runtime-credential.js +572 -0
- package/dist/runtime.d.ts +413 -0
- package/dist/runtime.js +825 -0
- package/dist/setup.d.ts +23 -47
- package/dist/setup.js +59 -116
- package/dist/skills.js +0 -7
- package/dist/status-cli.d.ts +27 -11
- package/dist/status-cli.js +121 -115
- package/dist/status-data.d.ts +116 -17
- package/dist/status-data.js +121 -38
- package/dist/subject.d.ts +126 -20
- package/dist/subject.js +215 -30
- package/dist/testing.d.ts +74 -38
- package/dist/testing.js +185 -68
- package/dist/tool-catalog.d.ts +53 -11
- package/dist/tool-catalog.js +164 -13
- package/dist/tool-metadata.d.ts +7 -6
- package/dist/tool-metadata.js +6 -5
- package/dist/types.d.ts +11 -1
- package/dist/uninstall.d.ts +71 -34
- package/dist/uninstall.js +217 -85
- package/dist/user-login.d.ts +9 -10
- package/dist/user-login.js +56 -75
- package/dist/watch-cli.d.ts +6 -0
- package/dist/watch-cli.js +217 -0
- package/package.json +4 -27
- package/assets/commands/dashboard.md +0 -34
- package/dist/dashboard-cli.d.ts +0 -8
- package/dist/dashboard-cli.js +0 -70
- package/dist/dev.d.ts +0 -103
- package/dist/dev.js +0 -583
- package/dist/interactive-setup.d.ts +0 -286
- package/dist/interactive-setup.js +0 -1734
- package/dist/local/jaeger-main.d.ts +0 -13
- package/dist/local/jaeger-main.js +0 -85
- package/dist/local/jaeger.d.ts +0 -50
- package/dist/local/jaeger.js +0 -162
- package/dist/otel/exporter.d.ts +0 -17
- package/dist/otel/exporter.js +0 -12
- package/dist/otel/index.d.ts +0 -2
- package/dist/otel/index.js +0 -8
- package/dist/otel/otlp.d.ts +0 -103
- package/dist/otel/otlp.js +0 -385
- package/dist/project-api-key.d.ts +0 -69
- package/dist/project-api-key.js +0 -147
- package/dist/setup-actions.d.ts +0 -232
- package/dist/setup-actions.js +0 -507
- package/dist/tracer.d.ts +0 -190
- package/dist/tracer.js +0 -481
- package/dist/watch-sandbox.d.ts +0 -9
- package/dist/watch-sandbox.js +0 -81
- package/dist/web/api.d.ts +0 -33
- package/dist/web/api.js +0 -294
- package/dist/web/launch.d.ts +0 -11
- package/dist/web/launch.js +0 -96
- package/dist/web/server.d.ts +0 -20
- package/dist/web/server.js +0 -233
- package/dist/web/types.d.ts +0 -65
- package/dist/web/types.js +0 -2
- package/dist/webapp/assets/index-Wucl4SZs.css +0 -1
- package/dist/webapp/assets/index-m-GtEdq0.js +0 -49
- package/dist/webapp/favicon.ico +0 -0
- package/dist/webapp/index.html +0 -15
package/dist/status-cli.js
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.printUserIdentitySection = printUserIdentitySection;
|
|
4
4
|
exports.printAgentIdentitySection = printAgentIdentitySection;
|
|
5
|
+
exports.printSubAgentIdentitiesSection = printSubAgentIdentitiesSection;
|
|
5
6
|
exports.printPermissionsSection = printPermissionsSection;
|
|
6
7
|
exports.runStatusCommand = runStatusCommand;
|
|
7
8
|
/**
|
|
8
9
|
* Unified `status` CLI implementation. Each harness's `cli/main.ts` `status`
|
|
9
10
|
* subcommand delegates here so onboarding readers see configuration, user
|
|
10
|
-
* identity, agent identity, permissions, and the
|
|
11
|
-
* registration block in a single pass.
|
|
11
|
+
* identity, agent identity, sub-agent identities, permissions, and the
|
|
12
|
+
* harness-specific plugin registration block in a single pass.
|
|
12
13
|
*
|
|
13
14
|
* The drill-down commands (`agent status`, `permissions status`) remain
|
|
14
15
|
* unchanged — this composes their inputs without altering their output.
|
|
@@ -16,15 +17,16 @@ exports.runStatusCommand = runStatusCommand;
|
|
|
16
17
|
const config_js_1 = require("./config.js");
|
|
17
18
|
const auth_store_js_1 = require("./auth-store.js");
|
|
18
19
|
const agent_auth_js_1 = require("./agent-auth.js");
|
|
19
|
-
const
|
|
20
|
-
const logger_js_1 = require("./logger.js");
|
|
21
|
-
const agent_auth_js_2 = require("./agent-auth.js");
|
|
20
|
+
const branding_js_1 = require("./branding.js");
|
|
22
21
|
const subject_js_1 = require("./subject.js");
|
|
22
|
+
const logger_js_1 = require("./logger.js");
|
|
23
|
+
const auth_js_1 = require("./auth.js");
|
|
24
|
+
const status_data_js_1 = require("./status-data.js");
|
|
23
25
|
const tool_catalog_js_1 = require("./tool-catalog.js");
|
|
24
26
|
const cli_js_1 = require("./cli.js");
|
|
25
27
|
const cli_invocation_js_1 = require("./cli-invocation.js");
|
|
26
28
|
function resolveNamespace() {
|
|
27
|
-
return process.env.ORY_PERMISSION_NAMESPACE ?? "
|
|
29
|
+
return process.env.ORY_PERMISSION_NAMESPACE ?? "AgentTool";
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Format a relative duration like "4h 32m" or "12s" for a future deadline.
|
|
@@ -65,6 +67,10 @@ function printUserIdentitySection() {
|
|
|
65
67
|
else {
|
|
66
68
|
console.log(` Token cache: present (expires in ${formatExpiresIn(tokens.expiresAt)})`);
|
|
67
69
|
}
|
|
70
|
+
const displayName = tokens.displayName ?? (0, auth_js_1.displayNameFromIdToken)(tokens.idToken);
|
|
71
|
+
if (displayName) {
|
|
72
|
+
console.log(` Name: ${displayName}`);
|
|
73
|
+
}
|
|
68
74
|
const subject = tokens.subject ? `user:${tokens.subject}` : "(no subject claim on cached token)";
|
|
69
75
|
console.log(` Subject: ${subject}`);
|
|
70
76
|
if (tokens.clientId) {
|
|
@@ -73,183 +79,182 @@ function printUserIdentitySection() {
|
|
|
73
79
|
}
|
|
74
80
|
/**
|
|
75
81
|
* Render the "Agent identity" block. Summarizes the resolved machine
|
|
76
|
-
* credential — static env override, persisted DCR, or unconfigured.
|
|
82
|
+
* credential — static env override, persisted DCR, or unconfigured. Each
|
|
83
|
+
* installed harness has its own agent registration, so the report is for
|
|
84
|
+
* `harness`'s identity only.
|
|
77
85
|
*/
|
|
78
|
-
function printAgentIdentitySection() {
|
|
86
|
+
function printAgentIdentitySection(harness) {
|
|
79
87
|
console.log("");
|
|
80
88
|
console.log("Agent identity (non-interactive):");
|
|
81
|
-
//
|
|
89
|
+
// The one static override takes precedence — surface it so the reader knows
|
|
82
90
|
// why DCR isn't running.
|
|
83
|
-
if (process.env.ORY_AGENT_API_KEY) {
|
|
84
|
-
console.log(" Source: static API key (ORY_AGENT_API_KEY)");
|
|
85
|
-
if (process.env.ORY_AGENT_SUBJECT_ID) {
|
|
86
|
-
console.log(` Subject: ${process.env.ORY_AGENT_SUBJECT_ID}`);
|
|
87
|
-
}
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
91
|
if (process.env.ORY_AGENT_CLIENT_ID && process.env.ORY_AGENT_CLIENT_SECRET) {
|
|
91
92
|
console.log(" Source: static client_credentials (ORY_AGENT_CLIENT_ID/SECRET)");
|
|
92
93
|
console.log(` Client ID: ${process.env.ORY_AGENT_CLIENT_ID}`);
|
|
93
|
-
const subject =
|
|
94
|
+
const subject = (0, subject_js_1.readAgentSubjectOverride)() ?? process.env.ORY_AGENT_CLIENT_ID;
|
|
94
95
|
console.log(` Subject: ${subject}`);
|
|
95
96
|
return;
|
|
96
97
|
}
|
|
97
|
-
const
|
|
98
|
-
if (!
|
|
98
|
+
const latest = (0, agent_auth_js_1.latestAgentRegistration)(harness);
|
|
99
|
+
if (!latest) {
|
|
99
100
|
console.log(" Source: not registered yet");
|
|
100
101
|
console.log(" Status: first session start will register an OAuth2 client (RFC 7591)");
|
|
101
102
|
return;
|
|
102
103
|
}
|
|
104
|
+
const { sessionKey, credentials: persisted } = latest;
|
|
103
105
|
const resolved = (0, config_js_1.resolveConfig)();
|
|
104
106
|
const mismatched = resolved.projectUrl && persisted.projectUrl !== resolved.projectUrl;
|
|
105
107
|
console.log(" Source: OAuth2 Dynamic Client Registration (RFC 7591)");
|
|
106
108
|
console.log(` Status: registered`);
|
|
109
|
+
console.log(` Name: ${(0, status_data_js_1.resolveDynamicName)(persisted)}`);
|
|
107
110
|
console.log(` Client ID: ${persisted.clientId}`);
|
|
108
|
-
const subject =
|
|
109
|
-
console.log(` Subject: ${subject}`);
|
|
111
|
+
const subject = (0, subject_js_1.readAgentSubjectOverride)() ?? persisted.clientId;
|
|
112
|
+
console.log(` Subject: ${subject_js_1.AGENT_NAMESPACE}:${subject}`);
|
|
110
113
|
console.log(` Registered: ${new Date(persisted.registeredAt * 1000).toISOString()}`);
|
|
114
|
+
console.log(` Session: ${sessionKey}`);
|
|
115
|
+
console.log(` Retained: ${(0, agent_auth_js_1.countAgentSessions)(harness)} session(s)`);
|
|
116
|
+
if (sessionKey !== config_js_1.SESSIONLESS_KEY) {
|
|
117
|
+
console.log(` Session ID: ${subject_js_1.AGENT_NAMESPACE}:${subject}|${sessionKey}`);
|
|
118
|
+
}
|
|
111
119
|
if (mismatched) {
|
|
112
120
|
console.log(` Warning: registered against ${persisted.projectUrl}, but current project URL is ${resolved.projectUrl}`);
|
|
113
121
|
console.log(" run `agent unregister` to clear stale credentials");
|
|
114
122
|
}
|
|
115
123
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Render the "Sub-agent identities" block — one entry per typed sub-agent
|
|
126
|
+
* (e.g. `Explore`, `general-purpose`) the agent has registered a distinct
|
|
127
|
+
* OAuth2 client for via DCR. All sub-agent identities are dynamic
|
|
128
|
+
* registrations. Scoped to `harness` — sub-agents belong to that harness's
|
|
129
|
+
* agent. A no-op when none exist yet.
|
|
130
|
+
*/
|
|
131
|
+
function printSubAgentIdentitiesSection(harness) {
|
|
132
|
+
const sessionKey = (0, agent_auth_js_1.latestAgentRegistration)(harness)?.sessionKey ?? (0, agent_auth_js_1.latestSubAgentSession)(harness);
|
|
133
|
+
const subAgents = sessionKey
|
|
134
|
+
? (0, agent_auth_js_1.loadAllSubAgentDynamicCredentials)(harness, sessionKey)
|
|
135
|
+
: {};
|
|
136
|
+
const types = Object.keys(subAgents).sort((a, b) => a.localeCompare(b));
|
|
137
|
+
console.log("");
|
|
138
|
+
console.log(`Sub-agent identities${sessionKey ? ` (session ${(0, branding_js_1.shortSessionLabel)(sessionKey)})` : ""}:`);
|
|
139
|
+
if (types.length === 0) {
|
|
140
|
+
console.log(" None registered yet — one is registered the first time the agent");
|
|
141
|
+
console.log(" spawns a typed sub-agent (e.g. a Task / Explore sub-agent).");
|
|
142
|
+
return;
|
|
134
143
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const check = {
|
|
151
|
-
namespace,
|
|
152
|
-
object: tool,
|
|
153
|
-
relation: "use",
|
|
154
|
-
...subject,
|
|
155
|
-
};
|
|
156
|
-
try {
|
|
157
|
-
const probe = await client.checkPermission(check, {
|
|
158
|
-
spanAttributes: { toolName: tool, source: "status_coverage" },
|
|
159
|
-
});
|
|
160
|
-
if (probe.allowed)
|
|
161
|
-
result.allowed++;
|
|
162
|
-
else
|
|
163
|
-
result.denied++;
|
|
164
|
-
}
|
|
165
|
-
catch (err) {
|
|
166
|
-
const ory = err;
|
|
167
|
-
result.errored++;
|
|
168
|
-
result.errorCode = result.errorCode ?? ory.code ?? "unknown";
|
|
144
|
+
const resolved = (0, config_js_1.resolveConfig)();
|
|
145
|
+
types.forEach((type, i) => {
|
|
146
|
+
if (i > 0)
|
|
147
|
+
console.log("");
|
|
148
|
+
const creds = subAgents[type];
|
|
149
|
+
const subject = creds.delegation?.delegatedBy
|
|
150
|
+
? `subagent:${creds.clientId} (delegated by ${creds.delegation.delegatedBy})`
|
|
151
|
+
: `subagent:${creds.clientId}`;
|
|
152
|
+
console.log(` ${type}:`);
|
|
153
|
+
console.log(` Name: ${(0, status_data_js_1.resolveDynamicName)(creds, type)}`);
|
|
154
|
+
console.log(` Client ID: ${creds.clientId}`);
|
|
155
|
+
console.log(` Subject: ${subject}`);
|
|
156
|
+
console.log(` Registered: ${new Date(creds.registeredAt * 1000).toISOString()}`);
|
|
157
|
+
if (resolved.projectUrl && creds.projectUrl !== resolved.projectUrl) {
|
|
158
|
+
console.log(` Warning: registered against ${creds.projectUrl}, but current project URL is ${resolved.projectUrl}`);
|
|
169
159
|
}
|
|
170
|
-
}
|
|
171
|
-
return result;
|
|
160
|
+
});
|
|
172
161
|
}
|
|
173
162
|
/**
|
|
174
|
-
* Render the "Permissions" block
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
163
|
+
* Render the "Permissions" block: the deny posture, the namespace, and the
|
|
164
|
+
* coverage of the harness's built-in tool catalog.
|
|
165
|
+
*
|
|
166
|
+
* The network probe runs only when a project URL is configured *and* a user
|
|
167
|
+
* identity is available (cached PKCE tokens or `ORY_USER_SUBJECT_ID`). When it
|
|
168
|
+
* runs, the reported **Mode is read live from the project** in the same pass, so
|
|
169
|
+
* this line answers "what would a tool call do right now?" rather than echoing a
|
|
170
|
+
* cache that is only refreshed at session start. On every other path the last
|
|
171
|
+
* cached value is reported, annotated as such.
|
|
178
172
|
*/
|
|
179
173
|
async function printPermissionsSection(binName, harness) {
|
|
180
174
|
const resolved = (0, config_js_1.resolveConfig)();
|
|
181
175
|
const namespace = resolveNamespace();
|
|
182
176
|
const catalog = (0, tool_catalog_js_1.getToolCatalog)(harness);
|
|
177
|
+
const cachedMode = `${resolved.permissionMode}${formatModeSuffix(resolved.permissionModeSource)}`;
|
|
183
178
|
console.log("");
|
|
184
179
|
console.log("Permissions:");
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (resolved.
|
|
188
|
-
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
if (!resolved.projectUrl) {
|
|
192
|
-
console.log(" Coverage: n/a (no project URL configured)");
|
|
193
|
-
return;
|
|
180
|
+
// Reasons the probe can't run. Each reports the cached mode, since there is no
|
|
181
|
+
// way to read the live one without reaching the project.
|
|
182
|
+
if (!resolved.security.connected) {
|
|
183
|
+
return printNoCoverage(cachedMode, namespace, `n/a (Agent Security not connected — ${(0, config_js_1.describeSecurityGap)(resolved.security)})`);
|
|
194
184
|
}
|
|
195
185
|
if (catalog.length === 0) {
|
|
196
|
-
|
|
186
|
+
printNoCoverage(cachedMode, namespace, `n/a (no built-in catalog for harness "${harness}")`);
|
|
197
187
|
console.log(` known harnesses: ${tool_catalog_js_1.KNOWN_HARNESSES.join(", ")}`);
|
|
198
188
|
return;
|
|
199
189
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
console.log(
|
|
203
|
-
console.log(` or set ORY_USER_SUBJECT_ID to probe a known subject)`);
|
|
190
|
+
if (!(process.env.ORY_USER_SUBJECT_ID || isUserTokenUsable())) {
|
|
191
|
+
printNoCoverage(cachedMode, namespace, "n/a (no cached user identity — start a session once to sign in,");
|
|
192
|
+
console.log(" or set ORY_USER_SUBJECT_ID to probe a known subject)");
|
|
204
193
|
return;
|
|
205
194
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
//
|
|
209
|
-
|
|
195
|
+
// The probe reads the live mode in the same pass, so hold the Mode line until
|
|
196
|
+
// it returns rather than printing a cached value we are about to supersede.
|
|
197
|
+
//
|
|
198
|
+
// The progress line is carriage-return overwritten, which only renders as
|
|
199
|
+
// intended on a terminal — piped or redirected output would keep the literal
|
|
200
|
+
// \r and the spaces, so skip it entirely when stdout isn't a TTY.
|
|
201
|
+
const spinner = process.stdout.isTTY === true;
|
|
202
|
+
if (spinner)
|
|
203
|
+
process.stdout.write(" checking…\r");
|
|
204
|
+
const probe = await (0, status_data_js_1.probePermissionsCoverage)(harness);
|
|
205
|
+
if (spinner)
|
|
206
|
+
process.stdout.write(" ".repeat(40) + "\r");
|
|
210
207
|
if (!probe) {
|
|
211
|
-
|
|
212
|
-
return;
|
|
208
|
+
return printNoCoverage(cachedMode, namespace, "unavailable (no user identity could be resolved)");
|
|
213
209
|
}
|
|
214
210
|
const { total, allowed, denied, errored } = probe;
|
|
211
|
+
console.log(` Mode: ${probe.mode}${formatModeSuffix(probe.modeSource)}`);
|
|
212
|
+
console.log(` Namespace: ${namespace}`);
|
|
213
|
+
console.log(` Subject: ${probe.subject}`);
|
|
215
214
|
if (errored > 0 && allowed === 0 && denied === 0) {
|
|
216
215
|
console.log(` Coverage: probe failed (${probe.errorCode ?? "unknown"})`);
|
|
217
216
|
return;
|
|
218
217
|
}
|
|
219
218
|
const status = allowed === total
|
|
220
|
-
? `
|
|
219
|
+
? `fully granted (${allowed}/${total} built-in tools)`
|
|
221
220
|
: allowed === 0
|
|
222
|
-
? `
|
|
221
|
+
? `no grants (0/${total} built-in tools)`
|
|
223
222
|
: `partial (${allowed}/${total} built-in tools allowed)`;
|
|
224
223
|
console.log(` Coverage: ${status}`);
|
|
225
224
|
if (denied > 0) {
|
|
226
|
-
console.log(
|
|
225
|
+
console.log(" grant the missing tools in the Ory Console (Agent Security)");
|
|
227
226
|
}
|
|
228
227
|
else if (errored > 0) {
|
|
229
|
-
console.log(` ${errored} probe error(s) — run "${(0, cli_invocation_js_1.oryNpx)(binName)} permissions
|
|
228
|
+
console.log(` ${errored} probe error(s) — run "${(0, cli_invocation_js_1.oryNpx)(binName)} permissions" for details`);
|
|
230
229
|
}
|
|
231
230
|
}
|
|
231
|
+
/** The Mode / Namespace / Coverage lines for every path that can't probe. */
|
|
232
|
+
function printNoCoverage(mode, namespace, coverage) {
|
|
233
|
+
console.log(` Mode: ${mode}`);
|
|
234
|
+
console.log(` Namespace: ${namespace}`);
|
|
235
|
+
console.log(` Coverage: ${coverage}`);
|
|
236
|
+
}
|
|
232
237
|
function isUserTokenUsable() {
|
|
233
238
|
const tokens = (0, auth_store_js_1.loadTokens)();
|
|
234
239
|
return !!tokens && !(0, auth_store_js_1.isExpired)(tokens);
|
|
235
240
|
}
|
|
236
241
|
function formatModeSuffix(source) {
|
|
237
242
|
switch (source) {
|
|
238
|
-
case "
|
|
239
|
-
return " (from
|
|
240
|
-
case "
|
|
241
|
-
return " (
|
|
243
|
+
case "server":
|
|
244
|
+
return " (read from the Ory project)";
|
|
245
|
+
case "cache":
|
|
246
|
+
return " (cached — project unreachable)";
|
|
242
247
|
case "default":
|
|
243
|
-
return " (default)";
|
|
248
|
+
return " (default — not yet read from the project)";
|
|
244
249
|
}
|
|
245
250
|
}
|
|
246
251
|
/**
|
|
247
252
|
* Compose the unified `status` output for a plugin CLI. Sections render
|
|
248
253
|
* in this order: title → configuration → user identity → agent identity
|
|
249
|
-
* → permissions → hooks & plugin → environment →
|
|
250
|
-
*
|
|
254
|
+
* → sub-agent identities → permissions → hooks & plugin → environment →
|
|
255
|
+
* recent activity from the unified activity/debug log.
|
|
251
256
|
*
|
|
252
|
-
* Each section degrades gracefully —
|
|
257
|
+
* Each section degrades gracefully — Agent Security not connected
|
|
253
258
|
* mode, and empty token caches all surface as inline "n/a" lines rather
|
|
254
259
|
* than aborting the command.
|
|
255
260
|
*/
|
|
@@ -266,19 +271,20 @@ async function runStatusCommand(binName, harness, options) {
|
|
|
266
271
|
console.log("");
|
|
267
272
|
(0, cli_js_1.printOryConfig)();
|
|
268
273
|
printUserIdentitySection();
|
|
269
|
-
printAgentIdentitySection();
|
|
274
|
+
printAgentIdentitySection(harness);
|
|
275
|
+
printSubAgentIdentitiesSection(harness);
|
|
270
276
|
await printPermissionsSection(binName, harness);
|
|
271
277
|
if (options.printPluginSection) {
|
|
272
278
|
console.log("");
|
|
273
|
-
options.printPluginSection();
|
|
279
|
+
await options.printPluginSection();
|
|
274
280
|
}
|
|
275
281
|
(0, cli_js_1.printEnvironment)();
|
|
276
282
|
console.log("");
|
|
277
283
|
console.log("Recent activity:");
|
|
278
|
-
(0, cli_js_1.printTraceTail)(harness);
|
|
279
284
|
(0, cli_js_1.printLogTail)(harness);
|
|
280
285
|
console.log("");
|
|
281
|
-
console.log(`
|
|
286
|
+
console.log(` Live activity/debug: ${(0, cli_invocation_js_1.oryNpx)(binName)} watch`);
|
|
287
|
+
console.log(" Include verbose diagnostics: set ORY_AGENT_DEBUG=true before starting the harness");
|
|
282
288
|
console.log("");
|
|
283
289
|
console.log(`Drill into any section with:`);
|
|
284
290
|
console.log(` ${(0, cli_invocation_js_1.oryNpx)(binName)} agent status`);
|
package/dist/status-data.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured status data — the data-gathering half of the `status` command,
|
|
3
|
+
* shared by the text renderer ({@link file://./status-cli.ts}) and the local
|
|
4
|
+
* web dashboard. `collectStatusReport(harness)` returns a plain, serializable
|
|
5
|
+
* object mirroring every section `status` prints (configuration, user identity,
|
|
6
|
+
* agent identity, permissions coverage, recent activity), so the two surfaces
|
|
7
|
+
* never drift.
|
|
8
|
+
*
|
|
9
|
+
* The live permission-coverage probe ({@link probePermissionsCoverage}) lives
|
|
10
|
+
* here too and is imported back by `status-cli.ts`, so there is a single probe
|
|
11
|
+
* implementation.
|
|
12
|
+
*/
|
|
13
|
+
import { type PermissionMode, type SecurityConnection } from "./config.js";
|
|
14
|
+
import { type PermissionModeSource } from "./permission-mode.js";
|
|
1
15
|
import { type StatusSystemSection } from "./status-system.js";
|
|
2
16
|
export interface PermissionsCoverage {
|
|
3
17
|
total: number;
|
|
@@ -5,12 +19,27 @@ export interface PermissionsCoverage {
|
|
|
5
19
|
denied: number;
|
|
6
20
|
errored: number;
|
|
7
21
|
errorCode?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The **live** deny posture, read from the project during the same probe.
|
|
24
|
+
* `status` reports this rather than the cached `config.permissionMode`: the
|
|
25
|
+
* two can disagree (the cache is only refreshed at session start), and the
|
|
26
|
+
* cached one is the misleading answer to "what would a tool call do now?".
|
|
27
|
+
*/
|
|
28
|
+
mode: PermissionMode;
|
|
29
|
+
modeSource: PermissionModeSource;
|
|
30
|
+
/** The subject the probe actually checked as, e.g. `User:<id>`. */
|
|
31
|
+
subject: string;
|
|
8
32
|
}
|
|
9
33
|
/**
|
|
10
34
|
* Probe the harness's built-in tool catalog against Ory, returning how many
|
|
11
|
-
* tools the resolved user subject is allowed / denied / errored on
|
|
12
|
-
*
|
|
13
|
-
* identity). Never
|
|
35
|
+
* tools the resolved user subject is allowed / denied / errored on, plus the
|
|
36
|
+
* live permission mode and the subject that was checked. Returns undefined when
|
|
37
|
+
* a probe can't run (no project URL, empty catalog, no user identity). Never
|
|
38
|
+
* throws.
|
|
39
|
+
*
|
|
40
|
+
* Checks route through {@link resolveCheckRelation}, i.e. the `access` permit —
|
|
41
|
+
* the same relation the runtime gate evaluates — so a tool carrying an explicit
|
|
42
|
+
* block is reported as denied here too, exactly as a tool call would be.
|
|
14
43
|
*/
|
|
15
44
|
export declare function probePermissionsCoverage(harness: string): Promise<PermissionsCoverage | undefined>;
|
|
16
45
|
export interface StatusConfigSection {
|
|
@@ -24,19 +53,28 @@ export interface StatusConfigSection {
|
|
|
24
53
|
/** Human-readable project / workspace names captured at install (display only). */
|
|
25
54
|
projectName?: string;
|
|
26
55
|
workspaceName?: string;
|
|
27
|
-
apiKeyConfigured: boolean;
|
|
28
|
-
apiKeySource: "env" | "config" | "none";
|
|
29
56
|
oauth2ClientId?: string;
|
|
30
|
-
oauth2ClientIdSource: "env" | "config" | "
|
|
31
|
-
/** Display name of the shared PKCE user-login client.
|
|
32
|
-
*
|
|
57
|
+
oauth2ClientIdSource: "env" | "config" | "default";
|
|
58
|
+
/** Display name of the shared PKCE user-login client. Present only when the
|
|
59
|
+
* configured client id *is* the reserved shared-login id — a project may
|
|
60
|
+
* legitimately be pointed at some other public client (or at one provisioned
|
|
61
|
+
* before the id was reserved), and labelling that one with the shared
|
|
62
|
+
* client's name would claim an identity it does not have. */
|
|
33
63
|
oauth2ClientName?: string;
|
|
34
|
-
|
|
64
|
+
/** Whether Agent Security runs, derived from the project and broker URLs. */
|
|
65
|
+
security: SecurityConnection;
|
|
35
66
|
permissionMode: "observe" | "enforce";
|
|
36
|
-
permissionModeSource: "
|
|
67
|
+
permissionModeSource: "server" | "cache" | "default";
|
|
37
68
|
userSubjectNamespace?: string;
|
|
38
69
|
userSubjectNamespaceSource: "env" | "config" | "none";
|
|
70
|
+
/** The tool namespace tool-use checks are addressed under (`ORY_PERMISSION_NAMESPACE`
|
|
71
|
+
* → default `AgentTool`). This is the namespace the `access` permit is checked in. */
|
|
39
72
|
namespace: string;
|
|
73
|
+
/** The principal namespaces the model addresses subjects under — `User`, `Agent`,
|
|
74
|
+
* `SubAgent`, and the `Session` fallback. These are the subject namespaces the
|
|
75
|
+
* checked `namespace` references; sourced from the canonical OPL constants so the
|
|
76
|
+
* dashboard lists the whole model, not just the tool namespace. */
|
|
77
|
+
principalNamespaces: string[];
|
|
40
78
|
/** Whether debug logging is on (`ORY_AGENT_DEBUG=true`). Env-only, read at
|
|
41
79
|
* process start by the logger — not persisted config, so it's shown read-only. */
|
|
42
80
|
debugEnabled: boolean;
|
|
@@ -44,23 +82,70 @@ export interface StatusConfigSection {
|
|
|
44
82
|
export interface StatusUserSection {
|
|
45
83
|
tokenCache: "empty" | "present" | "stale";
|
|
46
84
|
subject?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Human-readable name for the signed-in user (email / name /
|
|
87
|
+
* preferred_username), decoded from the persisted id_token. Present only
|
|
88
|
+
* when the id_token carries a profile claim — i.e. the login requested the
|
|
89
|
+
* `profile` / `email` scopes. Absent otherwise; callers fall back to the
|
|
90
|
+
* subject id.
|
|
91
|
+
*/
|
|
92
|
+
displayName?: string;
|
|
47
93
|
expiresInSeconds?: number;
|
|
48
94
|
clientId?: string;
|
|
49
95
|
}
|
|
50
|
-
export type AgentIdentitySource = "
|
|
96
|
+
export type AgentIdentitySource = "static_client_credentials" | "dcr" | "unregistered";
|
|
51
97
|
export interface StatusAgentSection {
|
|
52
98
|
source: AgentIdentitySource;
|
|
99
|
+
/** Human-readable OAuth2 client_name for a DCR agent, when known. */
|
|
100
|
+
name?: string;
|
|
53
101
|
clientId?: string;
|
|
54
102
|
subject?: string;
|
|
55
103
|
registeredAt?: string;
|
|
104
|
+
/**
|
|
105
|
+
* The session whose credential this report describes, if any. Sessionless SDK
|
|
106
|
+
* callers report the reserved `sessionless` key.
|
|
107
|
+
*/
|
|
108
|
+
sessionKey?: string;
|
|
109
|
+
/**
|
|
110
|
+
* The narrower per-session subject for this run. Absent when there is no
|
|
111
|
+
* ambient session (an SDK integration with no session concept).
|
|
112
|
+
*/
|
|
113
|
+
sessionSubject?: string;
|
|
114
|
+
projectUrlMismatch?: {
|
|
115
|
+
registeredAgainst: string;
|
|
116
|
+
current: string;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A typed sub-agent's persisted DCR identity — one row per sub-agent type
|
|
121
|
+
* (e.g. `Explore`, `general-purpose`) the agent has spawned and registered.
|
|
122
|
+
* All sub-agent identities are dynamic registrations, so this always mirrors
|
|
123
|
+
* an `agent.subAgents[<harness>][<session>][<type>]` entry in the shared config
|
|
124
|
+
* — the report covers the newest session of the harness it is run for, since a
|
|
125
|
+
* sub-agent belongs to one specific run of that harness's agent.
|
|
126
|
+
*/
|
|
127
|
+
export interface StatusSubAgentSection {
|
|
128
|
+
/** Sub-agent type key (the config map key), e.g. `"Explore"`. */
|
|
129
|
+
subAgentType: string;
|
|
130
|
+
/** Human-readable OAuth2 client_name for this sub-agent, when known. */
|
|
131
|
+
name?: string;
|
|
132
|
+
clientId: string;
|
|
133
|
+
subject: string;
|
|
134
|
+
registeredAt?: string;
|
|
135
|
+
/** The delegator recorded at registration (`agent:<sub>`), when known. */
|
|
136
|
+
delegatedBy?: string;
|
|
56
137
|
projectUrlMismatch?: {
|
|
57
138
|
registeredAgainst: string;
|
|
58
139
|
current: string;
|
|
59
140
|
};
|
|
60
141
|
}
|
|
61
|
-
export type PermissionsCoverageStatus =
|
|
142
|
+
export type PermissionsCoverageStatus =
|
|
143
|
+
/** Agent Security isn't connected — no project URL and/or OAuth2 client id. */
|
|
144
|
+
"not_connected" | "no_catalog" | "no_user" | "fully_granted" | "partial" | "no_grants" | "probe_failed";
|
|
62
145
|
export interface StatusPermissionsSection {
|
|
63
146
|
mode: "observe" | "enforce";
|
|
147
|
+
/** Where `mode` came from: a live project read, the local cache, or the default. */
|
|
148
|
+
modeSource: PermissionModeSource;
|
|
64
149
|
namespace: string;
|
|
65
150
|
coverageStatus: PermissionsCoverageStatus;
|
|
66
151
|
coverage?: PermissionsCoverage;
|
|
@@ -71,26 +156,40 @@ export interface StatusActivityEntry {
|
|
|
71
156
|
parsed?: Record<string, unknown>;
|
|
72
157
|
}
|
|
73
158
|
export interface StatusActivitySection {
|
|
74
|
-
traceFile?: string;
|
|
75
|
-
traceCount: number;
|
|
76
|
-
recentSpans: StatusActivityEntry[];
|
|
77
159
|
logFile?: string;
|
|
78
160
|
logCount: number;
|
|
79
|
-
|
|
161
|
+
recentEvents: StatusActivityEntry[];
|
|
80
162
|
}
|
|
81
163
|
export interface StatusReport {
|
|
82
164
|
harness: string;
|
|
83
165
|
config: StatusConfigSection;
|
|
84
166
|
user: StatusUserSection;
|
|
85
167
|
agent: StatusAgentSection;
|
|
168
|
+
/** Persisted per-type sub-agent DCR identities (may be empty). */
|
|
169
|
+
subAgents: StatusSubAgentSection[];
|
|
86
170
|
permissions: StatusPermissionsSection;
|
|
87
171
|
activity: StatusActivitySection;
|
|
88
172
|
/** Core Ory service health (Kratos, Hydra, Keto) — the dashboard's "System information". */
|
|
89
173
|
system: StatusSystemSection;
|
|
90
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Human-readable name for a DCR agent / sub-agent credential: the persisted
|
|
177
|
+
* `client_name` when present, else a best-effort reconstruction from the
|
|
178
|
+
* harness and (for sub-agents) type. Reconstruction uses the current hostname,
|
|
179
|
+
* which may differ from the registration host for credentials saved before the
|
|
180
|
+
* name was persisted — acceptable for a display-only label.
|
|
181
|
+
*/
|
|
182
|
+
export declare function resolveDynamicName(creds: {
|
|
183
|
+
clientName?: string;
|
|
184
|
+
harness?: string;
|
|
185
|
+
}, subAgentType?: string, harness?: string): string;
|
|
91
186
|
/**
|
|
92
187
|
* Gather the full structured status report for a harness. The permissions
|
|
93
188
|
* section runs a live network probe when a project URL and user identity are
|
|
94
189
|
* available (same conditions as the text `status` command).
|
|
190
|
+
*
|
|
191
|
+
* `sessionKey` is the run being reported on, when the caller is inside one. The
|
|
192
|
+
* standalone CLI passes none, so the report selects the harness's newest stored
|
|
193
|
+
* session rather than inventing an ambient session.
|
|
95
194
|
*/
|
|
96
|
-
export declare function collectStatusReport(harness: string): Promise<StatusReport>;
|
|
195
|
+
export declare function collectStatusReport(harness: string, sessionKey?: string): Promise<StatusReport>;
|