@ory/argus 1.1.0 → 1.2.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/dist/auth.d.ts CHANGED
@@ -52,6 +52,8 @@ export interface PkceLoginOptions {
52
52
  isHeadless?: () => boolean;
53
53
  /** Optional AbortSignal to cancel the login (e.g. on shutdown). */
54
54
  signal?: AbortSignal;
55
+ /** @internal Injectable seam for testing default-fetch TLS setup. */
56
+ configureSystemCaTrust?: () => void;
55
57
  }
56
58
  export type PkceLoginOutcome = {
57
59
  kind: "ok";
@@ -119,6 +121,8 @@ export declare function refreshAccessToken(args: {
119
121
  projectUrl: string;
120
122
  clientId: string;
121
123
  refreshToken: string;
124
+ /** @internal Injectable seam for testing default-fetch TLS setup. */
125
+ configureSystemCaTrust?: () => void;
122
126
  }): Promise<OryOAuth2Tokens>;
123
127
  /**
124
128
  * Best-effort human-readable name for the signed-in user, pulled from the
package/dist/auth.js CHANGED
@@ -60,6 +60,7 @@ const node_url_1 = require("node:url");
60
60
  const fs = __importStar(require("node:fs"));
61
61
  const path = __importStar(require("node:path"));
62
62
  const branding_js_1 = require("./branding.js");
63
+ const runtime_credential_js_1 = require("./runtime-credential.js");
63
64
  /** Loopback ports tried in order. All must be registered as redirect URIs on the Ory OAuth2 client. */
64
65
  exports.LOOPBACK_PORTS = [47823, 47824, 47825, 47826];
65
66
  /**
@@ -202,6 +203,7 @@ async function runPkceAttempt(options, scope, scopeFallbackPending) {
202
203
  redirectUri,
203
204
  code: result.code,
204
205
  codeVerifier,
206
+ configureSystemCaTrust: options.configureSystemCaTrust,
205
207
  });
206
208
  return { kind: "ok", tokens };
207
209
  }
@@ -516,6 +518,7 @@ async function exchangeCodeForTokens(args) {
516
518
  code_verifier: args.codeVerifier,
517
519
  });
518
520
  const tokenUrl = new node_url_1.URL("/oauth2/token", args.projectUrl).toString();
521
+ (args.configureSystemCaTrust ?? runtime_credential_js_1.configureSystemCaTrustForDefaultFetch)();
519
522
  const res = await fetch(tokenUrl, {
520
523
  method: "POST",
521
524
  headers: { "content-type": "application/x-www-form-urlencoded" },
@@ -558,6 +561,7 @@ async function refreshAccessToken(args) {
558
561
  refresh_token: args.refreshToken,
559
562
  });
560
563
  const tokenUrl = new node_url_1.URL("/oauth2/token", args.projectUrl).toString();
564
+ (args.configureSystemCaTrust ?? runtime_credential_js_1.configureSystemCaTrustForDefaultFetch)();
561
565
  const res = await fetch(tokenUrl, {
562
566
  method: "POST",
563
567
  headers: { "content-type": "application/x-www-form-urlencoded" },
@@ -19,8 +19,8 @@
19
19
  * name carrying *who* and *where*, so a shared project's resource list stays
20
20
  * legible and prunable: {@link agentClientName}, {@link projectApiKeyName}.
21
21
  *
22
- * Everything shares the {@link PRODUCT_NAME} prefix so the plugin's resources
23
- * group together and are instantly recognizable in a shared Ory Console.
22
+ * Display names stay short because the Console already provides the resource
23
+ * type and project context around them.
24
24
  */
25
25
  /** Human-readable umbrella name for everything this product creates. */
26
26
  export declare const PRODUCT_NAME = "Ory Agent Security";
@@ -58,7 +58,7 @@ export declare const USER_LOGIN_CLIENT_ID = "ory-agent-security-login";
58
58
  * installs onto one client, and {@link isUserLoginClient} is the only accepted
59
59
  * test for "is this the login client".
60
60
  */
61
- export declare const USER_LOGIN_CLIENT_NAME = "Ory Agent Security \u00B7 shared user login (all plugins)";
61
+ export declare const USER_LOGIN_CLIENT_NAME = "Agent Security login";
62
62
  /**
63
63
  * Whether a client is *the* shared user-login client, decided **only** by its
64
64
  * id. A client carrying {@link USER_LOGIN_CLIENT_NAME} under any other id is
package/dist/branding.js CHANGED
@@ -20,8 +20,8 @@
20
20
  * name carrying *who* and *where*, so a shared project's resource list stays
21
21
  * legible and prunable: {@link agentClientName}, {@link projectApiKeyName}.
22
22
  *
23
- * Everything shares the {@link PRODUCT_NAME} prefix so the plugin's resources
24
- * group together and are instantly recognizable in a shared Ory Console.
23
+ * Display names stay short because the Console already provides the resource
24
+ * type and project context around them.
25
25
  */
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
27
  exports.PERMISSION_NAMESPACE = exports.DEFAULT_PROJECT_NAME = exports.USER_LOGIN_SCOPE_CLI = exports.USER_LOGIN_SCOPE_OAUTH = exports.USER_LOGIN_SCOPES = exports.USER_LOGIN_BASE_SCOPES = exports.USER_LOGIN_CLIENT_NAME = exports.USER_LOGIN_CLIENT_ID = exports.PRODUCT_NAME = void 0;
@@ -65,7 +65,7 @@ exports.USER_LOGIN_CLIENT_ID = "ory-agent-security-login";
65
65
  * installs onto one client, and {@link isUserLoginClient} is the only accepted
66
66
  * test for "is this the login client".
67
67
  */
68
- exports.USER_LOGIN_CLIENT_NAME = `${exports.PRODUCT_NAME} · shared user login (all plugins)`;
68
+ exports.USER_LOGIN_CLIENT_NAME = "Agent Security login";
69
69
  /**
70
70
  * Whether a client is *the* shared user-login client, decided **only** by its
71
71
  * id. A client carrying {@link USER_LOGIN_CLIENT_NAME} under any other id is
@@ -111,11 +111,11 @@ function agentClientName(opts) {
111
111
  const session = sessionId?.trim() ? ` · ${shortSessionLabel(sessionId)}` : "";
112
112
  if (subAgentType) {
113
113
  const scope = harness ? `${harness}/${subAgentType}` : subAgentType;
114
- return `${exports.PRODUCT_NAME} · sub-agent · ${scope}${session} @ ${host}`;
114
+ return `Sub-agent · ${scope}${session} @ ${host}`;
115
115
  }
116
116
  return harness
117
- ? `${exports.PRODUCT_NAME} · agent · ${harness}${session} @ ${host}`
118
- : `${exports.PRODUCT_NAME} · agent${session} @ ${host}`;
117
+ ? `Agent · ${harness}${session} @ ${host}`
118
+ : `Agent${session} @ ${host}`;
119
119
  }
120
120
  /** How much of a session id goes into a display label. */
121
121
  const SESSION_LABEL_LENGTH = 8;
@@ -147,5 +147,5 @@ function shortSessionLabel(sessionId) {
147
147
  function projectApiKeyName(opts) {
148
148
  const who = opts.user && opts.user !== "agent:unknown" ? opts.user : null;
149
149
  const where = who ? `${who} @ ${opts.host}` : opts.host;
150
- return `${exports.PRODUCT_NAME}: Permission Checks - ${where}`;
150
+ return `Permission checks · ${where}`;
151
151
  }
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "repo": "ory-agent-plugins",
3
- "commit": "fc87fd73772d79007d1072c605ede76de42792ce",
4
- "commitShort": "fc87fd7",
3
+ "commit": "3be96aff052e866da1488acd848667d0c5974975",
4
+ "commitShort": "3be96af",
5
5
  "branch": "main",
6
- "commitDate": "2026-08-30T17:10:01-07:00",
6
+ "commitDate": "2026-09-03T17:55:10-07:00",
7
7
  "dirty": false,
8
- "builtAt": "2026-08-31T00:13:34.583Z"
8
+ "builtAt": "2026-09-04T01:07:34.694Z"
9
9
  }
package/dist/cli.d.ts CHANGED
@@ -66,12 +66,10 @@ export declare function promptForProjectUrl(binName: string): Promise<string | n
66
66
  */
67
67
  export declare function interactiveConfigPrompt(binName: string): Promise<boolean>;
68
68
  /**
69
- * Run the `agent <subcommand>` family of CLI commands. These manage the
70
- * agent's dynamic OAuth2 client registration (RFC 7591). Subcommands:
69
+ * Run the `agent <subcommand>` family of CLI commands. Subcommands:
71
70
  *
72
- * - `status` — print the persisted DCR identity, if any.
73
- * - `unregister` — best-effort RFC 7592 DELETE on the registered
74
- * client, then clear the persisted block.
71
+ * - `status` — inspect the actor-bound runtime credential.
72
+ * - `unregister` — clean up legacy OAuth registrations.
75
73
  *
76
74
  * Each installed harness owns its own agent identity, so both subcommands act
77
75
  * on `harness`'s registration by default. `--all` widens them to every
package/dist/cli.js CHANGED
@@ -50,6 +50,7 @@ const agent_auth_js_1 = require("./agent-auth.js");
50
50
  const logger_js_1 = require("./logger.js");
51
51
  const cli_invocation_js_1 = require("./cli-invocation.js");
52
52
  const client_js_1 = require("./client.js");
53
+ const status_data_js_1 = require("./status-data.js");
53
54
  /**
54
55
  * Shared `configure` command implementation for all plugin CLIs.
55
56
  *
@@ -286,8 +287,12 @@ function printEnvironment() {
286
287
  ["ORY_SDK_URL", process.env.ORY_SDK_URL, false],
287
288
  ["ORY_AGENT_SECURITY_URL", process.env.ORY_AGENT_SECURITY_URL, false],
288
289
  ["ORY_PROJECT_ID", process.env.ORY_PROJECT_ID, false],
289
- ["ORY_AGENT_CLIENT_ID", process.env.ORY_AGENT_CLIENT_ID, false],
290
290
  ["ORY_OAUTH2_CLIENT_ID", process.env.ORY_OAUTH2_CLIENT_ID, false],
291
+ [
292
+ "ORY_AGENT_API_KEY",
293
+ process.env.ORY_AGENT_API_KEY ? "(set)" : undefined,
294
+ false,
295
+ ],
291
296
  [
292
297
  "ORY_USER_OAUTH2_TOKEN",
293
298
  process.env.ORY_USER_OAUTH2_TOKEN ? "(set)" : undefined,
@@ -515,12 +520,10 @@ async function interactiveConfigPrompt(binName) {
515
520
  return false;
516
521
  }
517
522
  /**
518
- * Run the `agent <subcommand>` family of CLI commands. These manage the
519
- * agent's dynamic OAuth2 client registration (RFC 7591). Subcommands:
523
+ * Run the `agent <subcommand>` family of CLI commands. Subcommands:
520
524
  *
521
- * - `status` — print the persisted DCR identity, if any.
522
- * - `unregister` — best-effort RFC 7592 DELETE on the registered
523
- * client, then clear the persisted block.
525
+ * - `status` — inspect the actor-bound runtime credential.
526
+ * - `unregister` — clean up legacy OAuth registrations.
524
527
  *
525
528
  * Each installed harness owns its own agent identity, so both subcommands act
526
529
  * on `harness`'s registration by default. `--all` widens them to every
@@ -534,8 +537,8 @@ async function runAgentCommand(binName, harness, args) {
534
537
  console.log(`Usage: ${binName} agent <subcommand> [--all]`);
535
538
  console.log("");
536
539
  console.log("Subcommands:");
537
- console.log(" status Show the registered agent OAuth2 clients (one per session)");
538
- console.log(" unregister Delete the registered agent clients and clear local state");
540
+ console.log(" status Show actor-bound runtime credential availability");
541
+ console.log(" unregister Delete legacy OAuth registrations and clear legacy state");
539
542
  console.log("");
540
543
  console.log("Options:");
541
544
  console.log(` --all Act on every harness's agent client, not just ${harness}'s`);
@@ -544,7 +547,7 @@ async function runAgentCommand(binName, harness, args) {
544
547
  const all = args.includes("--all");
545
548
  switch (sub) {
546
549
  case "status":
547
- runAgentStatus(harness, all);
550
+ await runAgentStatus(harness, all);
548
551
  return 0;
549
552
  case "unregister":
550
553
  return await runAgentUnregister(harness, all);
@@ -571,32 +574,30 @@ function selectAgentRegistrations(harness, all) {
571
574
  return entries.sort((a, b) => b.credentials.registeredAt - a.credentials.registeredAt ||
572
575
  a.harness.localeCompare(b.harness));
573
576
  }
574
- function runAgentStatus(harness, all) {
575
- const registrations = selectAgentRegistrations(harness, all);
576
- console.log("Agent identity (Dynamic Client Registration)");
577
- console.log("=============================================");
577
+ async function runAgentStatus(harness, all) {
578
+ const config = (0, config_js_1.loadConfig)();
579
+ const harnesses = all
580
+ ? [...new Set([
581
+ ...(config.installedHarnesses ?? []),
582
+ ...Object.keys(config.delegationAnchors ?? {}),
583
+ ])].sort()
584
+ : [harness];
585
+ console.log("Agent identity (actor-bound runtime)");
586
+ console.log("====================================");
578
587
  console.log("");
579
- if (registrations.length === 0) {
580
- console.log(all
581
- ? " No registered agent clients for any harness. Each install registers"
582
- : ` No registered agent client for ${harness}. Each install registers`);
583
- console.log(" one on its first session start, using the user's bearer (or");
584
- console.log(" ORY_AGENT_REGISTRATION_TOKEN) as the initial access token.");
588
+ if (harnesses.length === 0) {
589
+ console.log(" No installed harnesses found.");
585
590
  return;
586
591
  }
587
- for (const { harness: key, sessionKey, credentials: persisted } of registrations) {
592
+ for (const key of harnesses) {
593
+ const sessionKey = (0, status_data_js_1.latestRuntimeSession)(key);
594
+ const identity = await (0, status_data_js_1.inspectRuntimeAgentIdentity)(key, sessionKey);
588
595
  console.log(` harness: ${key}`);
589
596
  console.log(` session: ${sessionKey}`);
590
- console.log(` client_id: ${persisted.clientId}`);
591
- console.log(` client_secret: ${persisted.clientSecret ? "(set)" : "(not set — public client)"}`);
592
- console.log(` registered_at: ${new Date(persisted.registeredAt * 1000).toISOString()}`);
593
- console.log(` project_url: ${persisted.projectUrl}`);
594
- if (persisted.registrationClientUri) {
595
- console.log(` management_uri: ${persisted.registrationClientUri}`);
596
- }
597
- if (persisted.registrationAccessToken) {
598
- console.log(` registration_token: (set — used to manage/delete this client)`);
599
- }
597
+ console.log(" method: Talos API key");
598
+ console.log(` source: ${identity.source === "talos_environment" ? "ORY_AGENT_API_KEY" : "OS credential store"}`);
599
+ console.log(` status: ${identity.source === "unavailable" ? "not found (enrollment runs at session start)" : "available"}`);
600
+ console.log(` actor_id: ${identity.subject ?? "resolved by Agent Security at request time"}`);
600
601
  console.log("");
601
602
  }
602
603
  }
package/dist/config.d.ts CHANGED
@@ -68,7 +68,7 @@ export interface OryAgentDynamicCredentials {
68
68
  harness?: string;
69
69
  /**
70
70
  * The human-readable OAuth2 `client_name` this registration was issued
71
- * under (e.g. `"Ory Agent Security · agent · claude-code @ host"`). Kept only
71
+ * under (e.g. `"Agent · claude-code @ host"`). Kept only
72
72
  * on a fresh registration response for immediate display; never persisted.
73
73
  * Later callers reconstruct a best-effort name from the outer harness key.
74
74
  */
package/dist/opl.js CHANGED
@@ -415,7 +415,8 @@ function buildAgentSecurityOpl(namespace = exports.DEFAULT_NAMESPACE, shellNames
415
415
  renderDelegationNamespaceClass(),
416
416
  "",
417
417
  "// Registered credential groups used to apply posture by harness or sub-agent type.",
418
- renderAgentTypeNamespaceClass(exports.AGENT_TYPE_NAMESPACE, subject_js_1.AGENT_NAMESPACE),
418
+ "// Delegated Sub-Agents also belong to their parent harness group.",
419
+ renderAgentTypeNamespaceClass(exports.AGENT_TYPE_NAMESPACE, `${subject_js_1.AGENT_NAMESPACE} | ${subject_js_1.SUBAGENT_NAMESPACE}`),
419
420
  "",
420
421
  renderAgentTypeNamespaceClass(exports.SUBAGENT_TYPE_NAMESPACE, subject_js_1.SUBAGENT_NAMESPACE),
421
422
  "",
@@ -1,21 +1,19 @@
1
+ import type { TalosCredentialStore } from "./runtime-credential.js";
1
2
  /**
2
3
  * Render the "User identity" block. The interactive PKCE login runs every
3
4
  * session; this shows the cached token's subject and expiry, if any.
4
5
  */
5
6
  export declare function printUserIdentitySection(): void;
6
7
  /**
7
- * Render the "Agent identity" block. Summarizes the resolved machine
8
- * credential static env override, persisted DCR, or unconfigured. Each
9
- * installed harness has its own agent registration, so the report is for
10
- * `harness`'s identity only.
8
+ * Render the actor-bound runtime credential used by this harness. The status
9
+ * command only reads credentials; enrollment remains a session-start action.
11
10
  */
12
- export declare function printAgentIdentitySection(harness: string): void;
11
+ export declare function printAgentIdentitySection(harness: string, credentialStore?: TalosCredentialStore): Promise<void>;
13
12
  /**
14
- * Render the "Sub-agent identities" block one entry per typed sub-agent
15
- * (e.g. `Explore`, `general-purpose`) the agent has registered a distinct
16
- * OAuth2 client for via DCR. All sub-agent identities are dynamic
17
- * registrations. Scoped to `harness` sub-agents belong to that harness's
18
- * agent. A no-op when none exist yet.
13
+ * Child credentials are keyed by session, type, and stable spawn id in the OS
14
+ * credential store. That store has no portable enumeration API, so status
15
+ * reports the active model rather than pretending the retired DCR config is
16
+ * the current set of sub-agents.
19
17
  */
20
18
  export declare function printSubAgentIdentitiesSection(harness: string): void;
21
19
  /**
@@ -16,9 +16,7 @@ exports.runStatusCommand = runStatusCommand;
16
16
  */
17
17
  const config_js_1 = require("./config.js");
18
18
  const auth_store_js_1 = require("./auth-store.js");
19
- const agent_auth_js_1 = require("./agent-auth.js");
20
19
  const branding_js_1 = require("./branding.js");
21
- const subject_js_1 = require("./subject.js");
22
20
  const logger_js_1 = require("./logger.js");
23
21
  const auth_js_1 = require("./auth.js");
24
22
  const status_data_js_1 = require("./status-data.js");
@@ -78,86 +76,46 @@ function printUserIdentitySection() {
78
76
  }
79
77
  }
80
78
  /**
81
- * Render the "Agent identity" block. Summarizes the resolved machine
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.
79
+ * Render the actor-bound runtime credential used by this harness. The status
80
+ * command only reads credentials; enrollment remains a session-start action.
85
81
  */
86
- function printAgentIdentitySection(harness) {
82
+ async function printAgentIdentitySection(harness, credentialStore) {
87
83
  console.log("");
88
- console.log("Agent identity (non-interactive):");
89
- // The one static override takes precedence — surface it so the reader knows
90
- // why DCR isn't running.
91
- if (process.env.ORY_AGENT_CLIENT_ID && process.env.ORY_AGENT_CLIENT_SECRET) {
92
- console.log(" Source: static client_credentials (ORY_AGENT_CLIENT_ID/SECRET)");
93
- console.log(` Client ID: ${process.env.ORY_AGENT_CLIENT_ID}`);
94
- const subject = (0, subject_js_1.readAgentSubjectOverride)() ?? process.env.ORY_AGENT_CLIENT_ID;
95
- console.log(` Subject: ${subject}`);
96
- return;
97
- }
98
- const latest = (0, agent_auth_js_1.latestAgentRegistration)(harness);
99
- if (!latest) {
100
- console.log(" Source: not registered yet");
101
- console.log(" Status: first session start will register an OAuth2 client (RFC 7591)");
102
- return;
103
- }
104
- const { sessionKey, credentials: persisted } = latest;
105
- const resolved = (0, config_js_1.resolveConfig)();
106
- const mismatched = resolved.projectUrl && persisted.projectUrl !== resolved.projectUrl;
107
- console.log(" Source: OAuth2 Dynamic Client Registration (RFC 7591)");
108
- console.log(` Status: registered`);
109
- console.log(` Name: ${(0, status_data_js_1.resolveDynamicName)(persisted)}`);
110
- console.log(` Client ID: ${persisted.clientId}`);
111
- const subject = (0, subject_js_1.readAgentSubjectOverride)() ?? persisted.clientId;
112
- console.log(` Subject: ${subject_js_1.AGENT_NAMESPACE}:${subject}`);
113
- console.log(` Registered: ${new Date(persisted.registeredAt * 1000).toISOString()}`);
84
+ console.log("Agent identity (actor-bound runtime):");
85
+ const identity = await (0, status_data_js_1.inspectRuntimeAgentIdentity)(harness, undefined, credentialStore);
86
+ const sessionKey = identity.sessionKey ?? config_js_1.SESSIONLESS_KEY;
87
+ console.log(" Method: Talos API key");
114
88
  console.log(` Session: ${sessionKey}`);
115
- console.log(` Retained: ${(0, agent_auth_js_1.countAgentSessions)(harness)} session(s)`);
116
89
  if (sessionKey !== config_js_1.SESSIONLESS_KEY) {
117
- console.log(` Session ID: ${subject_js_1.AGENT_NAMESPACE}:${subject}|${sessionKey}`);
90
+ console.log(` Session ref: ${(0, branding_js_1.shortSessionLabel)(sessionKey)}`);
91
+ }
92
+ if (identity.source === "talos_environment") {
93
+ console.log(" Source: ORY_AGENT_API_KEY");
94
+ console.log(" Status: available");
95
+ }
96
+ else if (identity.source === "talos_os_store") {
97
+ console.log(" Source: OS credential store");
98
+ console.log(" Status: available");
118
99
  }
119
- if (mismatched) {
120
- console.log(` Warning: registered against ${persisted.projectUrl}, but current project URL is ${resolved.projectUrl}`);
121
- console.log(" run `agent unregister` to clear stale credentials");
100
+ else {
101
+ console.log(" Source: OS credential store");
102
+ console.log(" Status: not found (enrollment runs at session start)");
122
103
  }
104
+ console.log(` Actor ID: ${identity.subject ?? "resolved by Agent Security at request time"}`);
123
105
  }
124
106
  /**
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.
107
+ * Child credentials are keyed by session, type, and stable spawn id in the OS
108
+ * credential store. That store has no portable enumeration API, so status
109
+ * reports the active model rather than pretending the retired DCR config is
110
+ * the current set of sub-agents.
130
111
  */
131
112
  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));
113
+ const sessionKey = (0, status_data_js_1.latestRuntimeSession)(harness);
137
114
  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;
143
- }
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}`);
159
- }
160
- });
115
+ console.log(`Sub-agent identities (session ${(0, branding_js_1.shortSessionLabel)(sessionKey)}):`);
116
+ console.log(" Method: child Talos API key");
117
+ console.log(" Scope: one credential per stable sub-agent spawn");
118
+ console.log(" Source: OS credential store (resolved when the sub-agent starts)");
161
119
  }
162
120
  /**
163
121
  * Render the "Permissions" block: the deny posture, the namespace, and the
@@ -201,7 +159,7 @@ async function printPermissionsSection(binName, harness) {
201
159
  const spinner = process.stdout.isTTY === true;
202
160
  if (spinner)
203
161
  process.stdout.write(" checking…\r");
204
- const probe = await (0, status_data_js_1.probePermissionsCoverage)(harness);
162
+ const probe = await (0, status_data_js_1.probePermissionsCoverage)(harness, (0, status_data_js_1.latestRuntimeSession)(harness));
205
163
  if (spinner)
206
164
  process.stdout.write(" ".repeat(40) + "\r");
207
165
  if (!probe) {
@@ -271,7 +229,7 @@ async function runStatusCommand(binName, harness, options) {
271
229
  console.log("");
272
230
  (0, cli_js_1.printOryConfig)();
273
231
  printUserIdentitySection();
274
- printAgentIdentitySection(harness);
232
+ await printAgentIdentitySection(harness);
275
233
  printSubAgentIdentitiesSection(harness);
276
234
  await printPermissionsSection(binName, harness);
277
235
  if (options.printPluginSection) {
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { type PermissionMode, type SecurityConnection } from "./config.js";
14
14
  import { type PermissionModeSource } from "./permission-mode.js";
15
+ import type { TalosCredentialStore } from "./runtime-credential.js";
15
16
  import { type StatusSystemSection } from "./status-system.js";
16
17
  export interface PermissionsCoverage {
17
18
  total: number;
@@ -42,7 +43,7 @@ export interface PermissionsCoverage {
42
43
  * Checks use the same default-allow `use` permit as the runtime gate. A false
43
44
  * result therefore means an explicit block, not missing grant coverage.
44
45
  */
45
- export declare function probePermissionsCoverage(harness: string): Promise<PermissionsCoverage | undefined>;
46
+ export declare function probePermissionsCoverage(harness: string, sessionKey?: string): Promise<PermissionsCoverage | undefined>;
46
47
  export interface StatusConfigSection {
47
48
  configPath: string;
48
49
  /** Whether a config file actually exists at `configPath` (vs. where one would be written). */
@@ -94,52 +95,50 @@ export interface StatusUserSection {
94
95
  expiresInSeconds?: number;
95
96
  clientId?: string;
96
97
  }
97
- export type AgentIdentitySource = "static_client_credentials" | "dcr" | "unregistered";
98
+ export type AgentIdentitySource = "talos_environment" | "talos_os_store" | "unavailable"
99
+ /** @deprecated Legacy status values retained for API compatibility. */
100
+ | "static_client_credentials" | "dcr" | "unregistered";
98
101
  export interface StatusAgentSection {
99
102
  source: AgentIdentitySource;
100
- /** Human-readable OAuth2 client_name for a DCR agent, when known. */
103
+ /** Broker-assigned actor id. Unavailable for an opaque environment credential. */
104
+ subject?: string;
105
+ /** Session identity inspected in the OS credential store. */
106
+ sessionKey?: string;
107
+ reason?: string;
108
+ /** @deprecated Runtime identities no longer use OAuth client registrations. */
101
109
  name?: string;
110
+ /** @deprecated Runtime identities no longer use OAuth client registrations. */
102
111
  clientId?: string;
103
- subject?: string;
112
+ /** @deprecated Runtime identities no longer use OAuth client registrations. */
104
113
  registeredAt?: string;
105
- /**
106
- * The session whose credential this report describes, if any. Sessionless SDK
107
- * callers report the reserved `sessionless` key.
108
- */
109
- sessionKey?: string;
110
- /**
111
- * The narrower per-session subject for this run. Absent when there is no
112
- * ambient session (an SDK integration with no session concept).
113
- */
114
+ /** @deprecated Runtime identities are already actor-bound. */
114
115
  sessionSubject?: string;
116
+ /** @deprecated Runtime credentials are keyed by project and cannot mismatch it. */
115
117
  projectUrlMismatch?: {
116
118
  registeredAgainst: string;
117
119
  current: string;
118
120
  };
119
121
  }
120
- /**
121
- * A typed sub-agent's persisted DCR identity — one row per sub-agent type
122
- * (e.g. `Explore`, `general-purpose`) the agent has spawned and registered.
123
- * All sub-agent identities are dynamic registrations, so this always mirrors
124
- * an `agent.subAgents[<harness>][<session>][<type>]` entry in the shared config
125
- * — the report covers the newest session of the harness it is run for, since a
126
- * sub-agent belongs to one specific run of that harness's agent.
127
- */
128
- export interface StatusSubAgentSection {
129
- /** Sub-agent type key (the config map key), e.g. `"Explore"`. */
122
+ export interface StatusSubAgentRuntimeSection {
123
+ source: "talos_os_store";
124
+ scope: "per_spawn";
125
+ sessionKey: string;
126
+ reason: string;
127
+ }
128
+ /** @deprecated DCR-shaped rows are retained in the type for API compatibility only. */
129
+ export interface StatusSubAgentLegacySection {
130
130
  subAgentType: string;
131
- /** Human-readable OAuth2 client_name for this sub-agent, when known. */
132
131
  name?: string;
133
132
  clientId: string;
134
133
  subject: string;
135
134
  registeredAt?: string;
136
- /** The delegator recorded at registration (`agent:<sub>`), when known. */
137
135
  delegatedBy?: string;
138
136
  projectUrlMismatch?: {
139
137
  registeredAgainst: string;
140
138
  current: string;
141
139
  };
142
140
  }
141
+ export type StatusSubAgentSection = StatusSubAgentRuntimeSection | StatusSubAgentLegacySection;
143
142
  export type PermissionsCoverageStatus =
144
143
  /** Agent Security isn't connected — no project URL and/or OAuth2 client id. */
145
144
  "not_connected" | "no_catalog" | "no_user" | "fully_allowed" | "partially_blocked" | "fully_blocked"
@@ -168,24 +167,15 @@ export interface StatusReport {
168
167
  config: StatusConfigSection;
169
168
  user: StatusUserSection;
170
169
  agent: StatusAgentSection;
171
- /** Persisted per-type sub-agent DCR identities (may be empty). */
170
+ /** Runtime child-identity model; credentials themselves remain in the OS store. */
172
171
  subAgents: StatusSubAgentSection[];
173
172
  permissions: StatusPermissionsSection;
174
173
  activity: StatusActivitySection;
175
174
  /** Core Ory service health (Kratos, Hydra, Keto) — the dashboard's "System information". */
176
175
  system: StatusSystemSection;
177
176
  }
178
- /**
179
- * Human-readable name for a DCR agent / sub-agent credential: the persisted
180
- * `client_name` when present, else a best-effort reconstruction from the
181
- * harness and (for sub-agents) type. Reconstruction uses the current hostname,
182
- * which may differ from the registration host for credentials saved before the
183
- * name was persisted — acceptable for a display-only label.
184
- */
185
- export declare function resolveDynamicName(creds: {
186
- clientName?: string;
187
- harness?: string;
188
- }, subAgentType?: string, harness?: string): string;
177
+ export declare function latestRuntimeSession(harness: string): string;
178
+ export declare function inspectRuntimeAgentIdentity(harness: string, sessionKey?: string, credentialStore?: TalosCredentialStore): Promise<StatusAgentSection>;
189
179
  /**
190
180
  * Gather the full structured status report for a harness. The permissions
191
181
  * section runs a live network probe when a project URL and user identity are
@@ -34,7 +34,8 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.probePermissionsCoverage = probePermissionsCoverage;
37
- exports.resolveDynamicName = resolveDynamicName;
37
+ exports.latestRuntimeSession = latestRuntimeSession;
38
+ exports.inspectRuntimeAgentIdentity = inspectRuntimeAgentIdentity;
38
39
  exports.collectStatusReport = collectStatusReport;
39
40
  /**
40
41
  * Structured status data — the data-gathering half of the `status` command,
@@ -52,12 +53,10 @@ const config_js_1 = require("./config.js");
52
53
  const permission_mode_js_1 = require("./permission-mode.js");
53
54
  const auth_store_js_1 = require("./auth-store.js");
54
55
  const agent_auth_js_1 = require("./agent-auth.js");
55
- const subject_js_1 = require("./subject.js");
56
56
  const client_js_1 = require("./client.js");
57
- const subject_js_2 = require("./subject.js");
57
+ const subject_js_1 = require("./subject.js");
58
58
  const branding_js_1 = require("./branding.js");
59
59
  const auth_js_1 = require("./auth.js");
60
- const node_os_1 = require("node:os");
61
60
  const tool_catalog_js_1 = require("./tool-catalog.js");
62
61
  const opl_js_1 = require("./opl.js");
63
62
  const fs = __importStar(require("node:fs"));
@@ -76,7 +75,7 @@ function resolveNamespace() {
76
75
  * Checks use the same default-allow `use` permit as the runtime gate. A false
77
76
  * result therefore means an explicit block, not missing grant coverage.
78
77
  */
79
- async function probePermissionsCoverage(harness) {
78
+ async function probePermissionsCoverage(harness, sessionKey = latestRuntimeSession(harness)) {
80
79
  const resolved = (0, config_js_1.resolveConfig)();
81
80
  if (!resolved.projectUrl)
82
81
  return undefined;
@@ -92,14 +91,20 @@ async function probePermissionsCoverage(harness) {
92
91
  if (tokens && !(0, auth_store_js_1.isExpired)(tokens)) {
93
92
  client.setUserPrincipal({ subject: tokens.subject, token: tokens.accessToken });
94
93
  }
95
- await (0, agent_auth_js_1.ensureAgentIdentity)(client, { projectUrl: resolved.projectUrl }).catch(() => {
96
- /* best-effort; the probe still runs with whatever credentials we have */
94
+ const runtime = await (0, agent_auth_js_1.resolveRuntimeAgentCredentials)({
95
+ projectUrl: resolved.projectUrl,
96
+ harness,
97
+ sessionId: sessionKey,
97
98
  });
98
- const subject = (0, subject_js_2.resolveUserSubject)(client);
99
- const subjectId = (0, subject_js_2.subjectLabel)(subject);
99
+ if (runtime.runtimeCredential)
100
+ client.setRuntimeCredential(runtime.runtimeCredential);
101
+ if (runtime.subject)
102
+ client.setAgentPrincipal({ subject: runtime.subject }, sessionKey);
103
+ const subject = (0, subject_js_1.resolveUserSubject)(client);
104
+ const subjectId = (0, subject_js_1.subjectLabel)(subject);
100
105
  if (subjectId === "agent:unknown")
101
106
  return undefined;
102
- const agentSubject = (0, subject_js_2.resolveAgentSubject)(client);
107
+ const agentSubject = (0, subject_js_1.resolveAgentSubject)(client);
103
108
  const live = await (0, permission_mode_js_1.resolvePermissionMode)(client, subject, {
104
109
  additionalSubjects: agentSubject ? [{ scope: "agent", subject: agentSubject }] : [],
105
110
  });
@@ -177,78 +182,41 @@ function collectUser() {
177
182
  clientId: tokens.clientId,
178
183
  };
179
184
  }
180
- /**
181
- * Human-readable name for a DCR agent / sub-agent credential: the persisted
182
- * `client_name` when present, else a best-effort reconstruction from the
183
- * harness and (for sub-agents) type. Reconstruction uses the current hostname,
184
- * which may differ from the registration host for credentials saved before the
185
- * name was persisted — acceptable for a display-only label.
186
- */
187
- function resolveDynamicName(creds, subAgentType, harness) {
188
- return (creds.clientName ??
189
- (0, branding_js_1.agentClientName)({
190
- harness: creds.harness ?? harness,
191
- host: (0, node_os_1.hostname)() || "unknown-host",
192
- subAgentType,
193
- }));
185
+ function latestRuntimeSession(harness) {
186
+ const sessions = Object.keys((0, config_js_1.loadConfig)().delegationAnchors?.[harness] ?? {});
187
+ return sessions.at(-1) ?? config_js_1.SESSIONLESS_KEY;
194
188
  }
195
- function collectAgent(harness, sessionKey) {
196
- if (process.env.ORY_AGENT_CLIENT_ID && process.env.ORY_AGENT_CLIENT_SECRET) {
189
+ async function inspectRuntimeAgentIdentity(harness, sessionKey = latestRuntimeSession(harness), credentialStore) {
190
+ const credentials = await (0, agent_auth_js_1.resolveRuntimeAgentCredentials)({
191
+ projectUrl: (0, config_js_1.resolveConfig)().projectUrl,
192
+ harness,
193
+ sessionId: sessionKey,
194
+ credentialStore,
195
+ });
196
+ if (credentials.kind === "talos") {
197
+ const source = process.env.ORY_AGENT_API_KEY?.trim()
198
+ ? "talos_environment"
199
+ : "talos_os_store";
197
200
  return {
198
- source: "static_client_credentials",
199
- clientId: process.env.ORY_AGENT_CLIENT_ID,
200
- subject: (0, subject_js_2.readAgentSubjectOverride)() ?? process.env.ORY_AGENT_CLIENT_ID,
201
+ source,
202
+ sessionKey,
203
+ subject: credentials.subject,
204
+ reason: credentials.reason,
201
205
  };
202
206
  }
203
- const selected = sessionKey
204
- ? (() => {
205
- const credentials = (0, agent_auth_js_1.loadAgentDynamicCredentials)(harness, sessionKey);
206
- return credentials ? { sessionKey, credentials } : undefined;
207
- })()
208
- : (0, agent_auth_js_1.latestAgentRegistration)(harness);
209
- if (!selected)
210
- return { source: "unregistered" };
211
- const { sessionKey: credentialSession, credentials: persisted } = selected;
212
- const resolved = (0, config_js_1.resolveConfig)();
213
- const mismatch = resolved.projectUrl && persisted.projectUrl !== resolved.projectUrl
214
- ? { registeredAgainst: persisted.projectUrl, current: resolved.projectUrl }
215
- : undefined;
216
- const subject = (0, subject_js_2.readAgentSubjectOverride)() ?? persisted.clientId;
217
207
  return {
218
- source: "dcr",
219
- name: resolveDynamicName(persisted, undefined, harness),
220
- sessionKey: credentialSession,
221
- ...(credentialSession === config_js_1.SESSIONLESS_KEY
222
- ? {}
223
- : { sessionSubject: `${subject_js_1.AGENT_NAMESPACE}:${subject}|${credentialSession}` }),
224
- clientId: persisted.clientId,
225
- subject,
226
- registeredAt: new Date(persisted.registeredAt * 1000).toISOString(),
227
- projectUrlMismatch: mismatch,
208
+ source: "unavailable",
209
+ sessionKey,
210
+ reason: credentials.reason,
228
211
  };
229
212
  }
230
213
  function collectSubAgents(harness, requestedSession) {
231
- const sessionKey = requestedSession
232
- ?? (0, agent_auth_js_1.latestAgentRegistration)(harness)?.sessionKey
233
- ?? (0, agent_auth_js_1.latestSubAgentSession)(harness);
234
- const persisted = sessionKey ? (0, agent_auth_js_1.loadAllSubAgentDynamicCredentials)(harness, sessionKey) : {};
235
- const resolved = (0, config_js_1.resolveConfig)();
236
- return Object.entries(persisted)
237
- .map(([subAgentType, creds]) => {
238
- const mismatch = resolved.projectUrl && creds.projectUrl !== resolved.projectUrl
239
- ? { registeredAgainst: creds.projectUrl, current: resolved.projectUrl }
240
- : undefined;
241
- return {
242
- subAgentType,
243
- name: resolveDynamicName(creds, subAgentType, harness),
244
- clientId: creds.clientId,
245
- subject: creds.clientId,
246
- registeredAt: new Date(creds.registeredAt * 1000).toISOString(),
247
- delegatedBy: creds.delegation?.delegatedBy,
248
- projectUrlMismatch: mismatch,
249
- };
250
- })
251
- .sort((a, b) => a.subAgentType.localeCompare(b.subAgentType));
214
+ return [{
215
+ source: "talos_os_store",
216
+ scope: "per_spawn",
217
+ sessionKey: requestedSession ?? latestRuntimeSession(harness),
218
+ reason: "Child credentials are resolved by stable sub-agent type and spawn id at runtime",
219
+ }];
252
220
  }
253
221
  async function collectPermissions(harness) {
254
222
  const resolved = (0, config_js_1.resolveConfig)();
@@ -325,7 +293,7 @@ async function collectStatusReport(harness, sessionKey) {
325
293
  harness,
326
294
  config: collectConfig(harness),
327
295
  user: collectUser(),
328
- agent: collectAgent(harness, sessionKey),
296
+ agent: await inspectRuntimeAgentIdentity(harness, sessionKey ?? latestRuntimeSession(harness)),
329
297
  subAgents: collectSubAgents(harness, sessionKey),
330
298
  permissions: await collectPermissions(harness),
331
299
  activity: collectActivity(harness),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/argus",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Ory Argus: the core API for building authentication, authorization, and audit into AI agent harness plugins, extensions, and custom integrations",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ory.com",