@ory/argus 0.13.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +31 -45
  2. package/assets/commands/temporal-up.md +1 -1
  3. package/assets/skills/auth-setup/SKILL.md +1 -1
  4. package/assets/skills/local-dev/SKILL.md +17 -7
  5. package/assets/skills/ory-build-agent/SKILL.md +43 -97
  6. package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -18
  7. package/assets/skills/ory-temporal-worker/SKILL.md +38 -42
  8. package/assets/skills/permissions-onboarding/SKILL.md +131 -104
  9. package/dist/adapters.d.ts +93 -30
  10. package/dist/adapters.js +464 -136
  11. package/dist/agent-auth.d.ts +258 -68
  12. package/dist/agent-auth.js +998 -202
  13. package/dist/auth-store.d.ts +37 -2
  14. package/dist/auth-store.js +37 -3
  15. package/dist/auth.d.ts +40 -4
  16. package/dist/auth.js +247 -19
  17. package/dist/bash-parser.d.ts +98 -0
  18. package/dist/bash-parser.js +396 -0
  19. package/dist/branding.d.ts +128 -0
  20. package/dist/branding.js +151 -0
  21. package/dist/build-info.json +4 -4
  22. package/dist/cli-invocation.d.ts +1 -1
  23. package/dist/cli-invocation.js +2 -1
  24. package/dist/cli.d.ts +20 -29
  25. package/dist/cli.js +271 -278
  26. package/dist/client.d.ts +175 -138
  27. package/dist/client.js +672 -391
  28. package/dist/config.d.ts +249 -57
  29. package/dist/config.js +486 -62
  30. package/dist/context.d.ts +10 -0
  31. package/dist/context.js +21 -0
  32. package/dist/contract-suite.d.ts +8 -8
  33. package/dist/contract-suite.js +88 -69
  34. package/dist/denial.d.ts +36 -3
  35. package/dist/denial.js +79 -10
  36. package/dist/event-reporter.d.ts +77 -0
  37. package/dist/event-reporter.js +776 -0
  38. package/dist/external-registrations-main.d.ts +10 -0
  39. package/dist/external-registrations-main.js +38 -0
  40. package/dist/external-registrations.d.ts +79 -0
  41. package/dist/external-registrations.js +188 -0
  42. package/dist/help-cli.d.ts +39 -0
  43. package/dist/help-cli.js +55 -0
  44. package/dist/hook-timeout.d.ts +64 -0
  45. package/dist/hook-timeout.js +88 -0
  46. package/dist/index.d.ts +31 -19
  47. package/dist/index.js +182 -31
  48. package/dist/lifecycle.d.ts +3 -3
  49. package/dist/lifecycle.js +38 -6
  50. package/dist/local/cli.js +11 -6
  51. package/dist/local/configs.d.ts +74 -18
  52. package/dist/local/configs.js +291 -84
  53. package/dist/local/health.d.ts +14 -0
  54. package/dist/local/health.js +50 -4
  55. package/dist/local/index.d.ts +2 -2
  56. package/dist/local/index.js +24 -10
  57. package/dist/local/manager.d.ts +20 -1
  58. package/dist/local/manager.js +160 -39
  59. package/dist/local/ports.d.ts +158 -0
  60. package/dist/local/ports.js +443 -0
  61. package/dist/local/seed.d.ts +22 -25
  62. package/dist/local/seed.js +88 -56
  63. package/dist/logger.d.ts +54 -25
  64. package/dist/logger.js +329 -63
  65. package/dist/mcp.d.ts +2 -2
  66. package/dist/mcp.js +10 -5
  67. package/dist/mirror-bootstrap.d.ts +48 -0
  68. package/dist/mirror-bootstrap.js +254 -0
  69. package/dist/opl.d.ts +289 -0
  70. package/dist/opl.js +446 -0
  71. package/dist/permission-mode.d.ts +87 -0
  72. package/dist/permission-mode.js +307 -0
  73. package/dist/permissions-cli.d.ts +13 -49
  74. package/dist/permissions-cli.js +154 -348
  75. package/dist/permissions.d.ts +148 -38
  76. package/dist/permissions.js +591 -45
  77. package/dist/post-install.d.ts +33 -0
  78. package/dist/post-install.js +127 -0
  79. package/dist/read-credential.d.ts +65 -0
  80. package/dist/read-credential.js +86 -0
  81. package/dist/registry/cli.js +5 -2
  82. package/dist/registry/config.d.ts +0 -17
  83. package/dist/registry/config.js +0 -23
  84. package/dist/registry/index.d.ts +1 -1
  85. package/dist/registry/index.js +2 -2
  86. package/dist/registry/manager.d.ts +4 -21
  87. package/dist/registry/manager.js +83 -55
  88. package/dist/runtime-credential.d.ts +140 -0
  89. package/dist/runtime-credential.js +572 -0
  90. package/dist/runtime.d.ts +408 -0
  91. package/dist/runtime.js +748 -0
  92. package/dist/setup.d.ts +23 -28
  93. package/dist/setup.js +57 -84
  94. package/dist/status-cli.d.ts +29 -13
  95. package/dist/status-cli.js +124 -144
  96. package/dist/status-data.d.ts +195 -0
  97. package/dist/status-data.js +333 -0
  98. package/dist/status-system.d.ts +24 -0
  99. package/dist/status-system.js +56 -0
  100. package/dist/subject.d.ts +126 -20
  101. package/dist/subject.js +215 -30
  102. package/dist/testing.d.ts +74 -38
  103. package/dist/testing.js +185 -68
  104. package/dist/tool-catalog.d.ts +53 -11
  105. package/dist/tool-catalog.js +164 -13
  106. package/dist/tool-metadata.d.ts +7 -6
  107. package/dist/tool-metadata.js +6 -5
  108. package/dist/types.d.ts +11 -1
  109. package/dist/uninstall.d.ts +74 -19
  110. package/dist/uninstall.js +224 -49
  111. package/dist/user-login.d.ts +22 -16
  112. package/dist/user-login.js +67 -96
  113. package/dist/watch-cli.d.ts +6 -0
  114. package/dist/watch-cli.js +217 -0
  115. package/package.json +3 -11
  116. package/dist/dev.d.ts +0 -103
  117. package/dist/dev.js +0 -584
  118. package/dist/interactive-setup.d.ts +0 -165
  119. package/dist/interactive-setup.js +0 -1546
  120. package/dist/local/jaeger-main.d.ts +0 -13
  121. package/dist/local/jaeger-main.js +0 -85
  122. package/dist/local/jaeger.d.ts +0 -50
  123. package/dist/local/jaeger.js +0 -162
  124. package/dist/otel/exporter.d.ts +0 -17
  125. package/dist/otel/exporter.js +0 -12
  126. package/dist/otel/index.d.ts +0 -2
  127. package/dist/otel/index.js +0 -8
  128. package/dist/otel/otlp.d.ts +0 -103
  129. package/dist/otel/otlp.js +0 -385
  130. package/dist/tracer.d.ts +0 -190
  131. package/dist/tracer.js +0 -481
  132. package/dist/watch-sandbox.d.ts +0 -9
  133. package/dist/watch-sandbox.js +0 -81
package/dist/uninstall.js CHANGED
@@ -1,90 +1,265 @@
1
1
  "use strict";
2
2
  /**
3
- * Credential teardown shared by every plugin's `uninstall` command.
3
+ * Config teardown shared by every plugin's `uninstall` command.
4
4
  *
5
- * Uninstalling a plugin removes all *authentication* state from the shared
6
- * config file while preserving *configuration* (project URL, OAuth2 client
7
- * id, audit mode, permission mode, user-login flag). The intent is that a
8
- * later re-install re-authenticates from scratch the user logs in again
9
- * and the agent registers a fresh dynamic client — rather than silently
10
- * inheriting stale credentials.
5
+ * `config.json` is a **single shared file** every installed harness plugin
6
+ * reads, so teardown is scoped: uninstalling one plugin must not knock the
7
+ * others back to an unconfigured state. Two scopes exist, and which one runs is
8
+ * decided from the install registry, not from a flag the caller guesses at:
11
9
  *
12
- * What is removed:
10
+ * - **`harness` scope** — other plugins are still installed. Only the
11
+ * departing harness's own identities go: the agent and sub-agent DCR
12
+ * clients of **every session it retains** are revoked (RFC 7592), and its
13
+ * entries are removed from `agent.dynamic` / `agent.subAgents`. Shared
14
+ * state — `projectUrl`, `oauth2ClientId`, the user's tokens, the permission
15
+ * mode — is left exactly as it was.
16
+ * - **`all` scope** — the departing harness was the last one installed, or
17
+ * the caller passed `purge: true`. Every harness's clients are revoked and
18
+ * the config file is left as an empty object, so a re-install starts from a
19
+ * clean slate rather than inheriting stale state.
20
+ *
21
+ * What an `all` teardown removes:
13
22
  * - the user's persisted OAuth2 tokens (`user`)
14
- * - the agent's dynamic-registration credentials and every sub-agent
15
- * registration (`agent`)
16
- * - the operator-supplied static agent API key (`apiKey`)
23
+ * - every harness's agent and sub-agent registrations, across all sessions
24
+ * (`agent`)
25
+ * - all configuration values (`projectUrl`, `projectId`, `projectName`,
26
+ * `workspaceName`, `oauth2ClientId`, `permissionModeCache`,
27
+ * `userSubjectNamespace`, `installedHarnesses`)
17
28
  * - any dangling PKCE-flight lock
18
29
  *
19
- * Before clearing local state, each dynamically-registered client (the
20
- * agent and each sub-agent) is revoked server-side via RFC 7592 so the
21
- * Ory project isn't left with orphaned OAuth2 clients accumulating across
22
- * install/uninstall cycles. Revocation is best-effort: failures warn and
23
- * local state is cleared regardless.
30
+ * Server-side teardown runs first, best-effort, and covers exactly the
31
+ * resources the plugin itself created: each dynamically-registered OAuth2
32
+ * client in scope (the agent and every sub-agent, for every retained session)
33
+ * is revoked via RFC 7592, so the Ory project isn't left with orphaned clients
34
+ * accumulating across install/uninstall cycles.
35
+ *
36
+ * Nothing in the project's **permission** state is touched. Grants, blocks,
37
+ * delegation edges, and the permission model are provisioned in the Ory
38
+ * Console (Agent Security) and owned there — the plugin has no Keto write
39
+ * path to unwind them with, and deleting an admin's grants on uninstall was
40
+ * never its call to make. The shared user-login PKCE OAuth2 client
41
+ * (`oauth2ClientId`) is likewise left in place: it is a public, identity-free
42
+ * client that every user and every harness install on the project reuses, so
43
+ * deleting it would break other installations. Both are only forgotten
44
+ * locally. Every server-side step is best-effort: failures warn and local
45
+ * state is cleared regardless.
24
46
  */
47
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
48
+ if (k2 === undefined) k2 = k;
49
+ var desc = Object.getOwnPropertyDescriptor(m, k);
50
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
51
+ desc = { enumerable: true, get: function() { return m[k]; } };
52
+ }
53
+ Object.defineProperty(o, k2, desc);
54
+ }) : (function(o, m, k, k2) {
55
+ if (k2 === undefined) k2 = k;
56
+ o[k2] = m[k];
57
+ }));
58
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
59
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
60
+ }) : function(o, v) {
61
+ o["default"] = v;
62
+ });
63
+ var __importStar = (this && this.__importStar) || (function () {
64
+ var ownKeys = function(o) {
65
+ ownKeys = Object.getOwnPropertyNames || function (o) {
66
+ var ar = [];
67
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
68
+ return ar;
69
+ };
70
+ return ownKeys(o);
71
+ };
72
+ return function (mod) {
73
+ if (mod && mod.__esModule) return mod;
74
+ var result = {};
75
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
76
+ __setModuleDefault(result, mod);
77
+ return result;
78
+ };
79
+ })();
25
80
  Object.defineProperty(exports, "__esModule", { value: true });
81
+ exports.resolveInstalledHarnesses = resolveInstalledHarnesses;
26
82
  exports.clearCredentialsForUninstall = clearCredentialsForUninstall;
83
+ const fs = __importStar(require("node:fs"));
27
84
  const config_js_1 = require("./config.js");
28
85
  const agent_auth_js_1 = require("./agent-auth.js");
29
86
  const auth_store_js_1 = require("./auth-store.js");
87
+ const runtime_js_1 = require("./runtime.js");
88
+ /**
89
+ * The harness plugins installed against the shared config, reconciled from
90
+ * every source that evidences one.
91
+ *
92
+ * The `installedHarnesses` registry is authoritative, but it only exists on
93
+ * configs written since it was introduced. Treating its absence as "nothing is
94
+ * installed" would make the first uninstall on an upgraded machine wipe the
95
+ * config every other plugin depends on — precisely the failure being fixed. So
96
+ * the runtime manifest (what each harness has wired) and the persisted
97
+ * credentials (which harnesses hold an identity) are folded in as evidence.
98
+ */
99
+ function resolveInstalledHarnesses(config = (0, config_js_1.loadConfig)()) {
100
+ const names = new Set(config.installedHarnesses ?? []);
101
+ for (const harness of Object.keys((0, runtime_js_1.readRuntimeManifest)().harnesses))
102
+ names.add(harness);
103
+ for (const harness of Object.keys(config.agent?.dynamic ?? {}))
104
+ names.add(harness);
105
+ for (const harness of Object.keys(config.agent?.subAgents ?? {}))
106
+ names.add(harness);
107
+ return [...names].sort();
108
+ }
30
109
  /**
31
- * Remove all authentication state from the shared config file, revoking
32
- * dynamically-registered clients server-side first. Preserves every
33
- * non-credential configuration value. Never throws.
110
+ * Tear down the departing harness's state, wiping the whole shared config only
111
+ * when nothing else still depends on it. Dynamically-registered clients in
112
+ * scope are revoked server-side first. Never throws.
34
113
  */
35
114
  async function clearCredentialsForUninstall(options = {}) {
36
115
  const log = options.log ?? ((msg) => console.log(msg));
37
116
  const revoke = options.revoke !== false;
117
+ const harness = options.harness?.trim() || undefined;
38
118
  const config = (0, config_js_1.loadConfig)();
39
- const dynamic = config.agent?.dynamic;
119
+ // Drop the departing harness from the registry first, so what remains is
120
+ // exactly the set of plugins that still need the shared config. Without a
121
+ // harness to attribute this uninstall to, nothing can be scoped — fall back
122
+ // to a full wipe.
123
+ const remainingHarnesses = harness
124
+ ? resolveInstalledHarnesses(config).filter((h) => h !== harness)
125
+ : [];
126
+ // Only write when there is something to remove — an uninstall against an
127
+ // already-empty config should not create a config file just to say so.
128
+ if (harness && config.installedHarnesses?.includes(harness)) {
129
+ (0, config_js_1.unregisterInstalledHarness)(harness);
130
+ }
131
+ const scope = harness && !options.purge && remainingHarnesses.length > 0 ? "harness" : "all";
132
+ const dynamic = config.agent?.dynamic ?? {};
40
133
  const subAgents = config.agent?.subAgents ?? {};
41
- const subAgentEntries = Object.entries(subAgents);
42
- const hadCredentials = Boolean(config.user || dynamic || subAgentEntries.length > 0 || config.apiKey);
43
- if (!hadCredentials) {
44
- log("No stored Ory credentials to remove.");
45
- return { hadCredentials: false, revoked: 0, revokeFailures: 0 };
134
+ const hadCredentials = Boolean(config.user ||
135
+ Object.keys(dynamic).length > 0 ||
136
+ Object.keys(subAgents).length > 0 ||
137
+ (config.agent?.retired?.length ?? 0) > 0);
138
+ if (Object.keys(config).length === 0) {
139
+ log("No Ory configuration to remove.");
140
+ return {
141
+ hadCredentials: false,
142
+ scope,
143
+ remainingHarnesses,
144
+ revoked: 0,
145
+ revokeFailures: 0,
146
+ };
147
+ }
148
+ // The clients this uninstall owns: this harness's on a scoped teardown, every
149
+ // harness's on a full one, across every retained session and child identity.
150
+ const inScope = (h) => scope === "all" || h === harness;
151
+ const targets = [];
152
+ for (const [h, bySession] of Object.entries(dynamic)) {
153
+ if (!inScope(h))
154
+ continue;
155
+ for (const [session, creds] of Object.entries(bySession)) {
156
+ targets.push({ label: `agent client (${h}/${session})`, creds });
157
+ }
158
+ }
159
+ for (const [h, bySession] of Object.entries(subAgents)) {
160
+ if (!inScope(h))
161
+ continue;
162
+ for (const [session, byType] of Object.entries(bySession)) {
163
+ for (const [type, creds] of Object.entries(byType)) {
164
+ targets.push({ label: `sub-agent client (${h}/${session}/${type})`, creds });
165
+ }
166
+ }
167
+ }
168
+ // Retention preserves the harness on retired records, so scoped teardown can
169
+ // revoke its own queue entries. Historical records without a harness remain
170
+ // unattributable and are swept only by a full teardown.
171
+ for (const creds of config.agent?.retired ?? []) {
172
+ if (scope === "all" || creds.harness === harness) {
173
+ targets.push({ label: "retired agent client", creds });
174
+ }
46
175
  }
47
176
  let revoked = 0;
48
177
  let revokeFailures = 0;
49
178
  if (revoke) {
50
- const targets = [];
51
- if (dynamic) {
52
- targets.push({
53
- label: "agent client",
54
- clientId: dynamic.clientId,
55
- result: () => (0, agent_auth_js_1.revokeAgentDynamicClient)(dynamic),
56
- });
57
- }
58
- for (const [type, creds] of subAgentEntries) {
59
- targets.push({
60
- label: `sub-agent client (${type})`,
61
- clientId: creds.clientId,
62
- result: () => (0, agent_auth_js_1.revokeAgentDynamicClient)(creds),
63
- });
64
- }
65
179
  for (const target of targets) {
66
- const outcome = await target.result();
180
+ const outcome = await (0, agent_auth_js_1.revokeAgentDynamicClient)(target.creds);
67
181
  if (outcome.status === "deleted") {
68
182
  revoked++;
69
- log(` Revoked ${target.label} ${target.clientId}.`);
183
+ log(` Revoked ${target.label} ${target.creds.clientId}.`);
70
184
  }
71
185
  else if (outcome.status === "skipped") {
72
186
  // No management credentials to DELETE with — nothing we can do
73
187
  // server-side. Not counted as a failure.
74
- log(` Could not revoke ${target.label} ${target.clientId} server-side (${outcome.message}). Clearing local state anyway.`);
188
+ log(` Could not revoke ${target.label} ${target.creds.clientId} server-side (${outcome.message}). Clearing local state anyway.`);
75
189
  }
76
190
  else {
77
191
  revokeFailures++;
78
192
  const detail = typeof outcome.httpStatus === "number"
79
193
  ? `HTTP ${outcome.httpStatus}`
80
194
  : (outcome.message ?? "unknown error");
81
- log(` Warning: server-side revoke of ${target.label} ${target.clientId} failed (${detail}). Clearing local state anyway.`);
195
+ log(` Warning: server-side revoke of ${target.label} ${target.creds.clientId} failed (${detail}). Clearing local state anyway.`);
82
196
  }
83
197
  }
84
198
  }
85
- // Drop every credential block; keep all configuration values.
86
- (0, config_js_1.saveConfig)({ user: null, agent: null, apiKey: null });
87
- (0, auth_store_js_1.clearPkceFlightLock)();
88
- log("Removed stored Ory credentials (user login, agent identity, API key).");
89
- return { hadCredentials: true, revoked, revokeFailures };
199
+ // The departing harness's asset tree (its skill/command trees, plus its
200
+ // unified activity/debug log) is state uniquely attributable to it, so
201
+ // it goes with the harness in either scope. On a full teardown every
202
+ // harness's tree goes, since the config they belong to is being wiped.
203
+ for (const h of scope === "all" ? resolveInstalledHarnesses(config) : [harness]) {
204
+ removeHarnessDataDir(h, log);
205
+ }
206
+ if (scope === "all") {
207
+ // Wipe the entire config file — credentials and configuration alike.
208
+ (0, config_js_1.mutateConfig)(() => ({}));
209
+ (0, auth_store_js_1.clearPkceFlightLock)();
210
+ log("Removed all Ory configuration and credentials.");
211
+ }
212
+ else {
213
+ (0, agent_auth_js_1.clearAgentDynamicCredentials)(harness);
214
+ (0, agent_auth_js_1.clearSubAgentDynamicCredentialsForHarness)(harness);
215
+ (0, config_js_1.mutateConfig)((current) => {
216
+ const next = { ...current };
217
+ if (current.agent?.retired) {
218
+ const agent = { ...current.agent };
219
+ agent.retired = current.agent.retired.filter((creds) => creds.harness !== harness);
220
+ if (agent.retired.length === 0)
221
+ delete agent.retired;
222
+ next.agent = agent;
223
+ }
224
+ if (current.delegationAnchors?.[harness]) {
225
+ const anchors = { ...current.delegationAnchors };
226
+ delete anchors[harness];
227
+ if (Object.keys(anchors).length > 0)
228
+ next.delegationAnchors = anchors;
229
+ else
230
+ delete next.delegationAnchors;
231
+ }
232
+ return next;
233
+ });
234
+ log(`Removed the ${harness} agent identities. Shared Ory configuration is kept for: ${remainingHarnesses.join(", ")}.`);
235
+ log(" Re-run with --purge to wipe the shared configuration and every harness's credentials.");
236
+ }
237
+ return {
238
+ hadCredentials,
239
+ scope,
240
+ remainingHarnesses,
241
+ revoked,
242
+ revokeFailures,
243
+ };
244
+ }
245
+ /**
246
+ * Remove a harness's asset tree under `<dataDir>/<harness>/`.
247
+ *
248
+ * Best-effort: the tree holds the harness's own skill/command assets plus its
249
+ * unified activity/debug log, and the log may still be open in this very
250
+ * process (or locked, on Windows). A failure to remove observability output is
251
+ * never a reason to fail an uninstall.
252
+ */
253
+ function removeHarnessDataDir(harness, log) {
254
+ const dir = (0, config_js_1.getHarnessDataDir)(harness);
255
+ try {
256
+ if (!fs.existsSync(dir))
257
+ return;
258
+ fs.rmSync(dir, { recursive: true, force: true });
259
+ log(` Removed ${harness} assets at ${dir}.`);
260
+ }
261
+ catch (err) {
262
+ const message = err instanceof Error ? err.message : String(err);
263
+ log(` Warning: could not remove ${dir} (${message}). Continuing.`);
264
+ }
90
265
  }
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * 1. Resolve config (env + ~/.config/ory-agent-plugins/config.json).
6
6
  * 2. If no project URL, prompt for one when a TTY is available;
7
- * otherwise skip with an audit span.
7
+ * otherwise skip with an audit event.
8
8
  * 3. If a session/oauth2 token is already in env, short-circuit ok.
9
9
  * 4. If persisted tokens are valid, return ok.
10
10
  * 5. If they are expired with a refresh_token, refresh.
@@ -14,14 +14,20 @@
14
14
  * paste the URL into any browser that can reach 127.0.0.1. Only
15
15
  * truly unattended (CI=true) environments short-circuit early.
16
16
  *
17
- * Every terminal path emits exactly one `user.auth` trace span so that
17
+ * Every terminal path emits exactly one `user.auth` activity event so that
18
18
  * the audit trail is complete regardless of outcome.
19
19
  *
20
- * The whole flow is a no-op (mode `disabled`) unless user login is
21
- * enabled either via the `ORY_USER_LOGIN` env var (values `1`, `true`,
22
- * `yes`, `on`) or persisted in the shared config file (`userLogin: true`,
23
- * set with `configure --user-login`). The env var overrides the config
24
- * file when set.
20
+ * The flow runs on **every** session and is **never** blocking: it
21
+ * establishes or refreshes the user identity for attribution, delegation,
22
+ * and permission-subject resolution, but a failure to authenticate never
23
+ * stops the session. Enforcement is governed solely by `permissionMode`
24
+ * (observe/enforce) at tool-call time — see `checkAndDecide`. The one
25
+ * exception is Agent Security not being connected at all (no project URL
26
+ * and OAuth2 client id), in which case there is nothing to sign in to and
27
+ * the flow no-ops with mode `not_connected`. When the user can't be
28
+ * authenticated the session still
29
+ * proceeds; under `enforce` a missing user identity naturally denies at
30
+ * the tool (no matching tuples), and under `observe` it is audited.
25
31
  *
26
32
  * This authenticates the *user* (the human at the keyboard). The
27
33
  * separate agent identity (the AI process making the calls) is resolved
@@ -30,16 +36,13 @@
30
36
  */
31
37
  import { OryAgentClient } from "./client.js";
32
38
  import { type OryOAuth2Tokens } from "./config.js";
33
- import { promptForProjectUrl } from "./cli.js";
34
39
  import { pkceLogin } from "./auth.js";
35
- export type UserLoginMode = "disabled" | "audit_only" | "env_token" | "ok" | "refreshed" | "skipped" | "declined" | "error";
40
+ export type UserLoginMode = "not_connected" | "env_token" | "ok" | "refreshed" | "skipped" | "declined" | "error";
36
41
  export interface UserLoginOptions {
37
42
  /** Bin name used in user-facing prompts (e.g. "ory-claude"). */
38
43
  binName: string;
39
- /** Logical harness name (used by the tracer). */
44
+ /** Logical harness name used for activity attribution. */
40
45
  harness: string;
41
- /** Whether the caller can hard-block on auth failure. */
42
- allowBlock: boolean;
43
46
  /**
44
47
  * Optional override of the PKCE login function — used by tests and by
45
48
  * harnesses that want to plug in a different flow.
@@ -47,13 +50,16 @@ export interface UserLoginOptions {
47
50
  loginFn?: typeof pkceLogin;
48
51
  /** Override TTY detection (for tests). */
49
52
  isTtyAvailableFn?: () => boolean;
50
- /** Override the prompt-for-URL step (for tests). */
51
- promptForProjectUrlFn?: typeof promptForProjectUrl;
52
53
  }
53
54
  export interface UserLoginDecision {
54
- /** Whether the caller should let the session proceed. */
55
+ /**
56
+ * Whether the caller should let the session proceed. User authentication
57
+ * is non-blocking, so this is **always** `true` — it is retained so the
58
+ * session-start adapters keep a stable shape. Enforcement lives in
59
+ * `permissionMode` at tool-call time, not here.
60
+ */
55
61
  proceed: boolean;
56
- /** Stable mode identifier for telemetry and tests. */
62
+ /** Stable mode identifier for activity logging and tests. */
57
63
  mode: UserLoginMode;
58
64
  /** Human-readable reason; safe to surface to the operator. */
59
65
  reason: string;