@ory/argus 0.13.9 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/assets/commands/dashboard.md +34 -0
- package/assets/skills/ory-build-agent/SKILL.md +11 -13
- package/assets/skills/ory-e2b-sandbox/SKILL.md +0 -1
- package/assets/skills/ory-temporal-worker/SKILL.md +8 -10
- package/assets/skills/permissions-onboarding/SKILL.md +3 -3
- package/dist/adapters.d.ts +12 -5
- package/dist/adapters.js +59 -10
- package/dist/agent-auth.d.ts +34 -3
- package/dist/agent-auth.js +58 -8
- package/dist/auth.d.ts +7 -0
- package/dist/auth.js +90 -5
- package/dist/branding.d.ts +67 -0
- package/dist/branding.js +81 -0
- package/dist/build-info.json +4 -4
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +13 -52
- package/dist/config.d.ts +48 -19
- package/dist/config.js +31 -26
- package/dist/contract-suite.d.ts +5 -3
- package/dist/contract-suite.js +13 -22
- package/dist/dashboard-cli.d.ts +8 -0
- package/dist/dashboard-cli.js +70 -0
- package/dist/dev.js +3 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +39 -3
- package/dist/interactive-setup.d.ts +144 -23
- package/dist/interactive-setup.js +412 -224
- package/dist/local/health.d.ts +14 -0
- package/dist/local/health.js +46 -0
- package/dist/local/manager.js +1 -3
- package/dist/local/seed.d.ts +9 -20
- package/dist/local/seed.js +26 -18
- package/dist/permissions-cli.js +1 -1
- package/dist/project-api-key.d.ts +69 -0
- package/dist/project-api-key.js +147 -0
- package/dist/registry/manager.js +62 -18
- package/dist/setup-actions.d.ts +232 -0
- package/dist/setup-actions.js +507 -0
- package/dist/setup.d.ts +19 -0
- package/dist/setup.js +44 -14
- package/dist/skills.js +7 -0
- package/dist/status-cli.d.ts +2 -2
- package/dist/status-cli.js +4 -30
- package/dist/status-data.d.ts +96 -0
- package/dist/status-data.js +250 -0
- package/dist/status-system.d.ts +24 -0
- package/dist/status-system.js +56 -0
- package/dist/uninstall.d.ts +33 -15
- package/dist/uninstall.js +65 -22
- package/dist/user-login.d.ts +16 -9
- package/dist/user-login.js +18 -28
- package/dist/web/api.d.ts +33 -0
- package/dist/web/api.js +294 -0
- package/dist/web/launch.d.ts +11 -0
- package/dist/web/launch.js +96 -0
- package/dist/web/server.d.ts +20 -0
- package/dist/web/server.js +233 -0
- package/dist/web/types.d.ts +65 -0
- package/dist/web/types.js +2 -0
- package/dist/webapp/assets/index-Wucl4SZs.css +1 -0
- package/dist/webapp/assets/index-m-GtEdq0.js +49 -0
- package/dist/webapp/favicon.ico +0 -0
- package/dist/webapp/index.html +15 -0
- package/package.json +17 -2
package/dist/auth.js
CHANGED
|
@@ -12,6 +12,39 @@
|
|
|
12
12
|
* package via dynamic import so the CJS-emitted core stays compatible
|
|
13
13
|
* with its ESM-only export shape.
|
|
14
14
|
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
15
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
49
|
exports.DEFAULT_LOGIN_TIMEOUT_MS = exports.LOOPBACK_PORTS = void 0;
|
|
17
50
|
exports.detectHeadless = detectHeadless;
|
|
@@ -20,9 +53,12 @@ exports.generateCodeVerifier = generateCodeVerifier;
|
|
|
20
53
|
exports.sha256Base64Url = sha256Base64Url;
|
|
21
54
|
exports.buildAuthorizeUrl = buildAuthorizeUrl;
|
|
22
55
|
exports.refreshAccessToken = refreshAccessToken;
|
|
56
|
+
exports.displayNameFromIdToken = displayNameFromIdToken;
|
|
23
57
|
const node_crypto_1 = require("node:crypto");
|
|
24
58
|
const node_http_1 = require("node:http");
|
|
25
59
|
const node_url_1 = require("node:url");
|
|
60
|
+
const fs = __importStar(require("node:fs"));
|
|
61
|
+
const path = __importStar(require("node:path"));
|
|
26
62
|
/** Loopback ports tried in order. All must be registered as redirect URIs on the Ory OAuth2 client. */
|
|
27
63
|
exports.LOOPBACK_PORTS = [47823, 47824, 47825, 47826];
|
|
28
64
|
/** Hard timeout if the user never returns to the browser. */
|
|
@@ -201,6 +237,10 @@ function waitForCallback(server, opts) {
|
|
|
201
237
|
return;
|
|
202
238
|
}
|
|
203
239
|
const url = new node_url_1.URL(req.url ?? "/", `http://127.0.0.1`);
|
|
240
|
+
if (url.pathname === "/favicon.ico") {
|
|
241
|
+
respondFavicon(res);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
204
244
|
if (url.pathname !== "/callback") {
|
|
205
245
|
respond(res, 404, "Not Found");
|
|
206
246
|
return;
|
|
@@ -238,18 +278,41 @@ function respondHtml(res, status, html) {
|
|
|
238
278
|
res.writeHead(status, { "content-type": "text/html; charset=utf-8" });
|
|
239
279
|
res.end(html);
|
|
240
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Serve the shared Ory favicon (identical to console.ory.com's) so the sign-in
|
|
283
|
+
* result page carries the same tab icon as the Console. It ships alongside the
|
|
284
|
+
* built dashboard at `dist/webapp/favicon.ico`; if that file isn't present
|
|
285
|
+
* (e.g. the webapp wasn't built), fall back to a 404 — the page still renders,
|
|
286
|
+
* just without a favicon. Same-origin on the loopback server, so no external
|
|
287
|
+
* request is made.
|
|
288
|
+
*/
|
|
289
|
+
function respondFavicon(res) {
|
|
290
|
+
// Compiled to dist/auth.js; the SPA (and its favicon) is built to dist/webapp.
|
|
291
|
+
const file = path.join(__dirname, "webapp", "favicon.ico");
|
|
292
|
+
try {
|
|
293
|
+
const buf = fs.readFileSync(file);
|
|
294
|
+
res.writeHead(200, {
|
|
295
|
+
"content-type": "image/x-icon",
|
|
296
|
+
"cache-control": "no-store",
|
|
297
|
+
});
|
|
298
|
+
res.end(buf);
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
respond(res, 404, "Not Found");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
241
304
|
/**
|
|
242
305
|
* The page the browser lands on after the OAuth2 redirect. The whole point is
|
|
243
306
|
* to make the next action unambiguous: on success it tells the user, in plain
|
|
244
307
|
* words, that they can close the tab and return to the terminal (the #1
|
|
245
|
-
* source of "is it done? do I close this?" confusion).
|
|
246
|
-
*
|
|
247
|
-
*
|
|
308
|
+
* source of "is it done? do I close this?" confusion). Inline styles only, no
|
|
309
|
+
* external requests — the only asset is the same-origin Ory favicon the
|
|
310
|
+
* loopback server serves — so it renders identically offline.
|
|
248
311
|
*/
|
|
249
312
|
function resultPage(kind) {
|
|
250
313
|
const view = {
|
|
251
314
|
success: {
|
|
252
|
-
accent: "#
|
|
315
|
+
accent: "#22C55E", // green — a positive "done" check
|
|
253
316
|
icon: "✓", // ✓
|
|
254
317
|
title: "Signed in to Ory",
|
|
255
318
|
body: "You can <strong>close this tab</strong> and return to your terminal — setup continues automatically.",
|
|
@@ -272,6 +335,7 @@ function resultPage(kind) {
|
|
|
272
335
|
<head>
|
|
273
336
|
<meta charset="utf-8">
|
|
274
337
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
338
|
+
<link rel="icon" href="/favicon.ico">
|
|
275
339
|
<title>${view.title}</title>
|
|
276
340
|
<style>
|
|
277
341
|
:root { color-scheme: light dark; }
|
|
@@ -381,6 +445,10 @@ function tokensFromTokenResponse(json, clientId, fallbackRefreshToken) {
|
|
|
381
445
|
}
|
|
382
446
|
/** Best-effort sub-claim extraction from a JWT id_token. Returns undefined on any failure. */
|
|
383
447
|
function subjectFromIdToken(idToken) {
|
|
448
|
+
return claimsFromIdToken(idToken)?.sub;
|
|
449
|
+
}
|
|
450
|
+
/** Best-effort JWT id_token payload decode. Returns undefined on any failure. */
|
|
451
|
+
function claimsFromIdToken(idToken) {
|
|
384
452
|
if (!idToken)
|
|
385
453
|
return undefined;
|
|
386
454
|
const parts = idToken.split(".");
|
|
@@ -388,9 +456,26 @@ function subjectFromIdToken(idToken) {
|
|
|
388
456
|
return undefined;
|
|
389
457
|
try {
|
|
390
458
|
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
|
|
391
|
-
return typeof payload
|
|
459
|
+
return payload && typeof payload === "object" ? payload : undefined;
|
|
392
460
|
}
|
|
393
461
|
catch {
|
|
394
462
|
return undefined;
|
|
395
463
|
}
|
|
396
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Best-effort human-readable name for the signed-in user, pulled from the
|
|
467
|
+
* id_token's identity claims — `email`, then `name`, then `preferred_username`.
|
|
468
|
+
* Returns undefined when the token carries none of them (e.g. an `openid`-only
|
|
469
|
+
* token), so callers fall back to the opaque subject id.
|
|
470
|
+
*/
|
|
471
|
+
function displayNameFromIdToken(idToken) {
|
|
472
|
+
const claims = claimsFromIdToken(idToken);
|
|
473
|
+
if (!claims)
|
|
474
|
+
return undefined;
|
|
475
|
+
for (const key of ["email", "name", "preferred_username"]) {
|
|
476
|
+
const v = claims[key];
|
|
477
|
+
if (typeof v === "string" && v.trim())
|
|
478
|
+
return v.trim();
|
|
479
|
+
}
|
|
480
|
+
return undefined;
|
|
481
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The umbrella brand and the names for every resource the installer creates in
|
|
3
|
+
* (or for) an Ory project. Centralized here so every install path — the web
|
|
4
|
+
* wizard, the TTY wizard, and the agent-identity gates — produces the same,
|
|
5
|
+
* self-describing names, and so the naming policy lives in one place.
|
|
6
|
+
*
|
|
7
|
+
* The policy has two tiers, because many users install these plugins against
|
|
8
|
+
* the **same** Ory project:
|
|
9
|
+
*
|
|
10
|
+
* - **Shared** resources (one per project, reused by every user/harness) get a
|
|
11
|
+
* **stable, identity-free** name so all installs find and reuse the one
|
|
12
|
+
* resource instead of duplicating it: {@link USER_LOGIN_CLIENT_NAME} and the
|
|
13
|
+
* permission namespace ({@link PERMISSION_NAMESPACE}).
|
|
14
|
+
* - **Per-installer** resources (many per project by design — confidential
|
|
15
|
+
* per-machine DCR credentials, write-once API keys) get an **attributable**
|
|
16
|
+
* name carrying *who* and *where*, so a shared project's resource list stays
|
|
17
|
+
* legible and prunable: {@link agentClientName}, {@link projectApiKeyName}.
|
|
18
|
+
*
|
|
19
|
+
* Everything shares the {@link PRODUCT_NAME} prefix so the plugin's resources
|
|
20
|
+
* group together and are instantly recognizable in a shared Ory Console.
|
|
21
|
+
*/
|
|
22
|
+
/** Human-readable umbrella name for everything this product creates. */
|
|
23
|
+
export declare const PRODUCT_NAME = "Ory Agent Security";
|
|
24
|
+
/**
|
|
25
|
+
* The public PKCE client the human's browser sign-in uses. It is a *public*
|
|
26
|
+
* client (no secret), so every user on a project shares the one client — the
|
|
27
|
+
* installer dedupes by this exact name. Stable and identity-free on purpose.
|
|
28
|
+
*/
|
|
29
|
+
export declare const USER_LOGIN_CLIENT_NAME = "Ory Agent Security \u00B7 user login (PKCE)";
|
|
30
|
+
/**
|
|
31
|
+
* Names an older installer may have given the shared user-login client. The
|
|
32
|
+
* reuse probe matches these too, so renaming the client never orphans one
|
|
33
|
+
* created by a previous install (which would then mint a duplicate).
|
|
34
|
+
*/
|
|
35
|
+
export declare const LEGACY_USER_LOGIN_CLIENT_NAMES: string[];
|
|
36
|
+
/** All names the shared user-login client may carry, newest first. */
|
|
37
|
+
export declare const USER_LOGIN_CLIENT_NAMES: string[];
|
|
38
|
+
/** Default name for a project the installer creates. Harness-agnostic, since a
|
|
39
|
+
* team typically points several harnesses at one shared project. */
|
|
40
|
+
export declare const DEFAULT_PROJECT_NAME = "Ory Agent Security";
|
|
41
|
+
/** The shared permission-model namespace (an OPL class name, so it must stay a
|
|
42
|
+
* bare identifier — no spaces/branding — and stable across installs). */
|
|
43
|
+
export declare const PERMISSION_NAMESPACE = "AgentTools";
|
|
44
|
+
/**
|
|
45
|
+
* The client_name for an agent's (or sub-agent's) OAuth2 identity registered
|
|
46
|
+
* via DCR. These are confidential, per-machine credentials — many per shared
|
|
47
|
+
* project by design — so the name is attributable: the harness it belongs to
|
|
48
|
+
* and the host it was registered from (plus the sub-agent type, when it is one).
|
|
49
|
+
*/
|
|
50
|
+
export declare function agentClientName(opts: {
|
|
51
|
+
harness?: string;
|
|
52
|
+
host: string;
|
|
53
|
+
subAgentType?: string;
|
|
54
|
+
}): string;
|
|
55
|
+
/**
|
|
56
|
+
* The name for a project API key minted for runtime permission checks. Ory only
|
|
57
|
+
* returns a key's secret at creation, so a key can't be reused across machines
|
|
58
|
+
* — each installer that mints one gets its own. The name therefore carries the
|
|
59
|
+
* signed-in *user* (the axis that matters on a shared project) plus the host, so
|
|
60
|
+
* a team admin can tell whose key is whose and prune stale ones. No timestamp:
|
|
61
|
+
* the Ory Console's key listing already shows a "Date Added" column. `user`
|
|
62
|
+
* falls back to the host alone when it isn't resolvable (e.g. login skipped).
|
|
63
|
+
*/
|
|
64
|
+
export declare function projectApiKeyName(opts: {
|
|
65
|
+
host: string;
|
|
66
|
+
user?: string;
|
|
67
|
+
}): string;
|
package/dist/branding.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The umbrella brand and the names for every resource the installer creates in
|
|
4
|
+
* (or for) an Ory project. Centralized here so every install path — the web
|
|
5
|
+
* wizard, the TTY wizard, and the agent-identity gates — produces the same,
|
|
6
|
+
* self-describing names, and so the naming policy lives in one place.
|
|
7
|
+
*
|
|
8
|
+
* The policy has two tiers, because many users install these plugins against
|
|
9
|
+
* the **same** Ory project:
|
|
10
|
+
*
|
|
11
|
+
* - **Shared** resources (one per project, reused by every user/harness) get a
|
|
12
|
+
* **stable, identity-free** name so all installs find and reuse the one
|
|
13
|
+
* resource instead of duplicating it: {@link USER_LOGIN_CLIENT_NAME} and the
|
|
14
|
+
* permission namespace ({@link PERMISSION_NAMESPACE}).
|
|
15
|
+
* - **Per-installer** resources (many per project by design — confidential
|
|
16
|
+
* per-machine DCR credentials, write-once API keys) get an **attributable**
|
|
17
|
+
* name carrying *who* and *where*, so a shared project's resource list stays
|
|
18
|
+
* legible and prunable: {@link agentClientName}, {@link projectApiKeyName}.
|
|
19
|
+
*
|
|
20
|
+
* Everything shares the {@link PRODUCT_NAME} prefix so the plugin's resources
|
|
21
|
+
* group together and are instantly recognizable in a shared Ory Console.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.PERMISSION_NAMESPACE = exports.DEFAULT_PROJECT_NAME = exports.USER_LOGIN_CLIENT_NAMES = exports.LEGACY_USER_LOGIN_CLIENT_NAMES = exports.USER_LOGIN_CLIENT_NAME = exports.PRODUCT_NAME = void 0;
|
|
25
|
+
exports.agentClientName = agentClientName;
|
|
26
|
+
exports.projectApiKeyName = projectApiKeyName;
|
|
27
|
+
/** Human-readable umbrella name for everything this product creates. */
|
|
28
|
+
exports.PRODUCT_NAME = "Ory Agent Security";
|
|
29
|
+
/**
|
|
30
|
+
* The public PKCE client the human's browser sign-in uses. It is a *public*
|
|
31
|
+
* client (no secret), so every user on a project shares the one client — the
|
|
32
|
+
* installer dedupes by this exact name. Stable and identity-free on purpose.
|
|
33
|
+
*/
|
|
34
|
+
exports.USER_LOGIN_CLIENT_NAME = `${exports.PRODUCT_NAME} · user login (PKCE)`;
|
|
35
|
+
/**
|
|
36
|
+
* Names an older installer may have given the shared user-login client. The
|
|
37
|
+
* reuse probe matches these too, so renaming the client never orphans one
|
|
38
|
+
* created by a previous install (which would then mint a duplicate).
|
|
39
|
+
*/
|
|
40
|
+
exports.LEGACY_USER_LOGIN_CLIENT_NAMES = ["ory-agent-plugin"];
|
|
41
|
+
/** All names the shared user-login client may carry, newest first. */
|
|
42
|
+
exports.USER_LOGIN_CLIENT_NAMES = [
|
|
43
|
+
exports.USER_LOGIN_CLIENT_NAME,
|
|
44
|
+
...exports.LEGACY_USER_LOGIN_CLIENT_NAMES,
|
|
45
|
+
];
|
|
46
|
+
/** Default name for a project the installer creates. Harness-agnostic, since a
|
|
47
|
+
* team typically points several harnesses at one shared project. */
|
|
48
|
+
exports.DEFAULT_PROJECT_NAME = exports.PRODUCT_NAME;
|
|
49
|
+
/** The shared permission-model namespace (an OPL class name, so it must stay a
|
|
50
|
+
* bare identifier — no spaces/branding — and stable across installs). */
|
|
51
|
+
exports.PERMISSION_NAMESPACE = "AgentTools";
|
|
52
|
+
/**
|
|
53
|
+
* The client_name for an agent's (or sub-agent's) OAuth2 identity registered
|
|
54
|
+
* via DCR. These are confidential, per-machine credentials — many per shared
|
|
55
|
+
* project by design — so the name is attributable: the harness it belongs to
|
|
56
|
+
* and the host it was registered from (plus the sub-agent type, when it is one).
|
|
57
|
+
*/
|
|
58
|
+
function agentClientName(opts) {
|
|
59
|
+
const { harness, host, subAgentType } = opts;
|
|
60
|
+
if (subAgentType) {
|
|
61
|
+
const scope = harness ? `${harness}/${subAgentType}` : subAgentType;
|
|
62
|
+
return `${exports.PRODUCT_NAME} · sub-agent · ${scope} @ ${host}`;
|
|
63
|
+
}
|
|
64
|
+
return harness
|
|
65
|
+
? `${exports.PRODUCT_NAME} · agent · ${harness} @ ${host}`
|
|
66
|
+
: `${exports.PRODUCT_NAME} · agent @ ${host}`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The name for a project API key minted for runtime permission checks. Ory only
|
|
70
|
+
* returns a key's secret at creation, so a key can't be reused across machines
|
|
71
|
+
* — each installer that mints one gets its own. The name therefore carries the
|
|
72
|
+
* signed-in *user* (the axis that matters on a shared project) plus the host, so
|
|
73
|
+
* a team admin can tell whose key is whose and prune stale ones. No timestamp:
|
|
74
|
+
* the Ory Console's key listing already shows a "Date Added" column. `user`
|
|
75
|
+
* falls back to the host alone when it isn't resolvable (e.g. login skipped).
|
|
76
|
+
*/
|
|
77
|
+
function projectApiKeyName(opts) {
|
|
78
|
+
const who = opts.user && opts.user !== "agent:unknown" ? opts.user : null;
|
|
79
|
+
const where = who ? `${who} @ ${opts.host}` : opts.host;
|
|
80
|
+
return `${exports.PRODUCT_NAME}: Permission Checks - ${where}`;
|
|
81
|
+
}
|
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"repo": "ory-agent-plugins",
|
|
3
|
-
"commit": "
|
|
4
|
-
"commitShort": "
|
|
3
|
+
"commit": "7568c163e59fba25d64ede49c092fcca108a43f2",
|
|
4
|
+
"commitShort": "7568c16",
|
|
5
5
|
"branch": "main",
|
|
6
|
-
"commitDate": "2026-07-
|
|
6
|
+
"commitDate": "2026-07-23T10:17:45-07:00",
|
|
7
7
|
"dirty": false,
|
|
8
|
-
"builtAt": "2026-07-
|
|
8
|
+
"builtAt": "2026-07-23T17:21:55.389Z"
|
|
9
9
|
}
|
package/dist/cli.d.ts
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* When `--project-url` is provided, requires the OAuth2 client id to be
|
|
9
9
|
* resolvable from one of: the `--oauth2-client-id` flag, the
|
|
10
10
|
* `ORY_OAUTH2_CLIENT_ID` env var, or an already-persisted value in the
|
|
11
|
-
* shared config. The PKCE browser flow
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* shared config. The PKCE browser flow (the user login runs every session)
|
|
12
|
+
* can't self-register that client — surfacing the requirement here keeps
|
|
13
|
+
* users from a silently-broken setup later.
|
|
14
14
|
*/
|
|
15
15
|
export declare function runConfigureCommand(binName: string, args: string[]): void;
|
|
16
16
|
/**
|
package/dist/cli.js
CHANGED
|
@@ -62,9 +62,9 @@ const client_js_1 = require("./client.js");
|
|
|
62
62
|
* When `--project-url` is provided, requires the OAuth2 client id to be
|
|
63
63
|
* resolvable from one of: the `--oauth2-client-id` flag, the
|
|
64
64
|
* `ORY_OAUTH2_CLIENT_ID` env var, or an already-persisted value in the
|
|
65
|
-
* shared config. The PKCE browser flow
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
* shared config. The PKCE browser flow (the user login runs every session)
|
|
66
|
+
* can't self-register that client — surfacing the requirement here keeps
|
|
67
|
+
* users from a silently-broken setup later.
|
|
68
68
|
*/
|
|
69
69
|
function runConfigureCommand(binName, args) {
|
|
70
70
|
let projectUrl;
|
|
@@ -72,9 +72,6 @@ function runConfigureCommand(binName, args) {
|
|
|
72
72
|
let apiKey;
|
|
73
73
|
let oauth2ClientId;
|
|
74
74
|
let auditOnly = false;
|
|
75
|
-
// `undefined` = not specified (leave the persisted value alone);
|
|
76
|
-
// true/false = explicit enable/disable of the interactive user login.
|
|
77
|
-
let userLogin;
|
|
78
75
|
// `undefined` = not specified; a string sets it; empty string ("") clears it
|
|
79
76
|
// (via --no-user-subject-namespace) to fall back to direct SubjectID.
|
|
80
77
|
let userSubjectNamespace;
|
|
@@ -98,12 +95,6 @@ function runConfigureCommand(binName, args) {
|
|
|
98
95
|
case "--audit-only":
|
|
99
96
|
auditOnly = true;
|
|
100
97
|
break;
|
|
101
|
-
case "--user-login":
|
|
102
|
-
userLogin = true;
|
|
103
|
-
break;
|
|
104
|
-
case "--no-user-login":
|
|
105
|
-
userLogin = false;
|
|
106
|
-
break;
|
|
107
98
|
case "--user-subject-namespace":
|
|
108
99
|
userSubjectNamespace = args[++i];
|
|
109
100
|
break;
|
|
@@ -117,28 +108,23 @@ function runConfigureCommand(binName, args) {
|
|
|
117
108
|
!apiKey &&
|
|
118
109
|
!oauth2ClientId &&
|
|
119
110
|
!auditOnly &&
|
|
120
|
-
userLogin === undefined &&
|
|
121
111
|
userSubjectNamespace === undefined) {
|
|
122
112
|
const resolved = (0, config_js_1.resolveConfig)();
|
|
123
113
|
const configPath = (0, config_js_1.getConfigPath)();
|
|
124
114
|
console.log("Ory Plugin Configuration");
|
|
125
115
|
console.log("========================");
|
|
126
116
|
console.log("");
|
|
127
|
-
console.log(`Config file: ${configPath}`);
|
|
117
|
+
console.log(`Config file: ${configPath}${fs.existsSync(configPath) ? "" : " (not created yet)"}`);
|
|
128
118
|
console.log(`Project URL: ${resolved.projectUrl ?? "(not set)"} [${resolved.projectUrlSource}]`);
|
|
129
119
|
console.log(`Project ID: ${resolved.projectId ?? "(not set)"} [${resolved.projectIdSource}]`);
|
|
130
120
|
console.log(`API Key: ${resolved.apiKey ? "(set)" : "(not set)"} [${resolved.apiKeySource}]`);
|
|
131
121
|
console.log(`OAuth2 Client ID: ${resolved.oauth2ClientId ?? "(not set)"} [${resolved.oauth2ClientIdSource}]`);
|
|
132
122
|
console.log(`Audit Only: ${resolved.auditOnly ? "yes" : "no"}`);
|
|
133
|
-
console.log(`User Login: ${resolved.userLogin ? "on" : "off"} [${resolved.userLoginSource}]`);
|
|
134
123
|
console.log(`User subject ns: ${resolved.userSubjectNamespace ?? "(direct subject id)"} [${resolved.userSubjectNamespaceSource}]`);
|
|
135
124
|
console.log("");
|
|
136
125
|
console.log("To configure:");
|
|
137
126
|
console.log(` ${(0, cli_invocation_js_1.oryNpx)(binName)} configure --project-url <URL> --oauth2-client-id <CLIENT_ID> [--api-key <KEY>]`);
|
|
138
127
|
console.log("");
|
|
139
|
-
console.log("To enable the interactive user login (PKCE browser flow at session start):");
|
|
140
|
-
console.log(` npx ${binName} configure --user-login (disable with --no-user-login)`);
|
|
141
|
-
console.log("");
|
|
142
128
|
console.log("To address the user as a SubjectSet in permission checks (must match your tuples):");
|
|
143
129
|
console.log(` ${(0, cli_invocation_js_1.oryNpx)(binName)} configure --user-subject-namespace User (clear with --no-user-subject-namespace)`);
|
|
144
130
|
console.log("");
|
|
@@ -151,20 +137,14 @@ function runConfigureCommand(binName, args) {
|
|
|
151
137
|
console.log(" # ORY_PROJECT_ID=<project uuid> is stored for admin operations (not an SDK URL).");
|
|
152
138
|
console.log(" export ORY_OAUTH2_CLIENT_ID=<public OAuth2 client id>");
|
|
153
139
|
console.log(" export ORY_AGENT_API_KEY=ory_pat_...");
|
|
154
|
-
console.log(" export ORY_USER_LOGIN=true");
|
|
155
140
|
return;
|
|
156
141
|
}
|
|
157
142
|
if (auditOnly) {
|
|
158
|
-
// Audit-only mode: set the kill switch
|
|
159
|
-
|
|
160
|
-
// later turned off; audit-only itself disables login regardless.
|
|
161
|
-
(0, config_js_1.saveConfig)({ auditOnly: true, ...(userLogin !== undefined ? { userLogin } : {}) });
|
|
143
|
+
// Audit-only mode: set the kill switch (disables auth and checks entirely).
|
|
144
|
+
(0, config_js_1.saveConfig)({ auditOnly: true });
|
|
162
145
|
const configPath = (0, config_js_1.getConfigPath)();
|
|
163
146
|
console.log(`Configuration saved to ${configPath}`);
|
|
164
147
|
console.log(" Mode: audit-only (logging enabled, auth and permission checks disabled)");
|
|
165
|
-
if (userLogin !== undefined) {
|
|
166
|
-
console.log(` User login: ${userLogin ? "on" : "off"} (takes effect when audit-only is disabled)`);
|
|
167
|
-
}
|
|
168
148
|
console.log("");
|
|
169
149
|
console.log("This configuration is shared across all Ory agent plugins.");
|
|
170
150
|
return;
|
|
@@ -207,34 +187,19 @@ function runConfigureCommand(binName, args) {
|
|
|
207
187
|
process.exit(1);
|
|
208
188
|
}
|
|
209
189
|
}
|
|
210
|
-
// Enabling user login needs a project URL and a public OAuth2 client id
|
|
211
|
-
// to complete the PKCE flow. Warn (don't block) if either is missing —
|
|
212
|
-
// the operator may supply them separately or via env before running.
|
|
213
|
-
if (userLogin === true) {
|
|
214
|
-
// resolveConfig() already folds in the ORY_SDK_URL alias and the config
|
|
215
|
-
// file; OR in the URL being set on this same invocation.
|
|
216
|
-
const nextProjectUrl = projectUrl ?? (0, config_js_1.resolveConfig)().projectUrl;
|
|
217
|
-
const nextClientId = oauth2ClientId ?? process.env.ORY_OAUTH2_CLIENT_ID ?? (0, config_js_1.loadConfig)().oauth2ClientId;
|
|
218
|
-
if (!nextProjectUrl || !nextClientId) {
|
|
219
|
-
const missing = [
|
|
220
|
-
!nextProjectUrl ? "a project URL (--project-url / --sdk-url / ORY_PROJECT_URL)" : null,
|
|
221
|
-
!nextClientId ? "an OAuth2 client id (--oauth2-client-id / ORY_OAUTH2_CLIENT_ID)" : null,
|
|
222
|
-
].filter(Boolean);
|
|
223
|
-
console.warn(`Warning: user login is enabled but still missing ${missing.join(" and ")}.\n` +
|
|
224
|
-
"The PKCE browser flow can't complete until both are configured.");
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
190
|
const update = {};
|
|
228
191
|
if (projectUrl)
|
|
229
192
|
update.projectUrl = projectUrl;
|
|
230
193
|
if (projectId)
|
|
231
194
|
update.projectId = projectId;
|
|
232
|
-
if (apiKey)
|
|
195
|
+
if (apiKey) {
|
|
233
196
|
update.apiKey = apiKey;
|
|
197
|
+
// A hand-supplied key has no known token id; drop any stale id so uninstall
|
|
198
|
+
// never tries to delete a different token by an id that no longer matches.
|
|
199
|
+
update.apiKeyId = null;
|
|
200
|
+
}
|
|
234
201
|
if (oauth2ClientId)
|
|
235
202
|
update.oauth2ClientId = oauth2ClientId;
|
|
236
|
-
if (userLogin !== undefined)
|
|
237
|
-
update.userLogin = userLogin;
|
|
238
203
|
// A non-empty namespace sets the SubjectSet namespace; the empty string
|
|
239
204
|
// (from --no-user-subject-namespace) clears it (null ⇒ delete the key).
|
|
240
205
|
if (userSubjectNamespace !== undefined) {
|
|
@@ -243,7 +208,7 @@ function runConfigureCommand(binName, args) {
|
|
|
243
208
|
// Configuring an actual connection (a slug-based URL, api key, or client id)
|
|
244
209
|
// implies leaving audit-only mode. A bare project id is only an admin
|
|
245
210
|
// identifier — it doesn't connect anything on its own — so it doesn't flip
|
|
246
|
-
// the flag
|
|
211
|
+
// the flag.
|
|
247
212
|
if (projectUrl || apiKey || oauth2ClientId)
|
|
248
213
|
update.auditOnly = false;
|
|
249
214
|
(0, config_js_1.saveConfig)(update);
|
|
@@ -257,13 +222,11 @@ function runConfigureCommand(binName, args) {
|
|
|
257
222
|
console.log(` API Key: (set)`);
|
|
258
223
|
if (oauth2ClientId)
|
|
259
224
|
console.log(` OAuth2 Client ID: ${oauth2ClientId}`);
|
|
260
|
-
if (userLogin !== undefined)
|
|
261
|
-
console.log(` User Login: ${userLogin ? "on" : "off"}`);
|
|
262
225
|
if (userSubjectNamespace !== undefined)
|
|
263
226
|
console.log(` User subject namespace: ${userSubjectNamespace === "" ? "(cleared — direct subject id)" : userSubjectNamespace}`);
|
|
264
227
|
console.log("");
|
|
265
228
|
console.log("This configuration is shared across all Ory agent plugins.");
|
|
266
|
-
console.log("Environment variables (ORY_PROJECT_URL, ORY_AGENT_API_KEY, ORY_OAUTH2_CLIENT_ID
|
|
229
|
+
console.log("Environment variables (ORY_PROJECT_URL, ORY_AGENT_API_KEY, ORY_OAUTH2_CLIENT_ID) take precedence when set.");
|
|
267
230
|
}
|
|
268
231
|
/**
|
|
269
232
|
* Print the "Configuration:" block showing Ory project URL and API key status.
|
|
@@ -280,7 +243,6 @@ function printOryConfig() {
|
|
|
280
243
|
console.log(` API Key: ${resolved.apiKey ? "(set)" : "NOT SET"} [source: ${resolved.apiKeySource}]`);
|
|
281
244
|
console.log(` OAuth2 Client: ${resolved.oauth2ClientId ?? "NOT SET"} [source: ${resolved.oauth2ClientIdSource}]`);
|
|
282
245
|
console.log(` Permission mode: ${resolved.permissionMode} [source: ${resolved.permissionModeSource}]`);
|
|
283
|
-
console.log(` User login: ${resolved.userLogin ? "on" : "off"} [source: ${resolved.userLoginSource}]`);
|
|
284
246
|
console.log(` Namespace: ${namespace}`);
|
|
285
247
|
console.log(` User subject ns: ${resolved.userSubjectNamespace ?? "(direct subject id)"} [source: ${resolved.userSubjectNamespaceSource}]`);
|
|
286
248
|
}
|
|
@@ -294,7 +256,6 @@ function printEnvironment() {
|
|
|
294
256
|
["ORY_PROJECT_URL", process.env.ORY_PROJECT_URL, false],
|
|
295
257
|
["ORY_SDK_URL", process.env.ORY_SDK_URL, false],
|
|
296
258
|
["ORY_PROJECT_ID", process.env.ORY_PROJECT_ID, false],
|
|
297
|
-
["ORY_USER_LOGIN", process.env.ORY_USER_LOGIN, false],
|
|
298
259
|
[
|
|
299
260
|
"ORY_AGENT_API_KEY",
|
|
300
261
|
process.env.ORY_AGENT_API_KEY ? "(set)" : undefined,
|
package/dist/config.d.ts
CHANGED
|
@@ -30,6 +30,27 @@ export interface OryUserCredentials {
|
|
|
30
30
|
* restarts re-use the same agent identity instead of re-registering on
|
|
31
31
|
* every session.
|
|
32
32
|
*/
|
|
33
|
+
/**
|
|
34
|
+
* The delegation edge recorded on a dynamically-registered OAuth2 client's
|
|
35
|
+
* `metadata` at registration time (see {@link OryAgentDynamicCredentials.delegation}).
|
|
36
|
+
*
|
|
37
|
+
* This is the **integrity anchor** for the delegation chain: it is bound to
|
|
38
|
+
* the OAuth2 client identity durably owned by Hydra / Ory Network and mirrored
|
|
39
|
+
* into local config, so the delegator can be resolved — and the derived Keto
|
|
40
|
+
* tuple rebuilt — even if the tuple is lost, corrupted, or never written.
|
|
41
|
+
*/
|
|
42
|
+
export interface OryDelegationRecord {
|
|
43
|
+
/** The delegator, as a namespaced subject: `user:<sub>` or `agent:<sub>`. */
|
|
44
|
+
delegatedBy: string;
|
|
45
|
+
/** Which edge of the chain this client sits on. */
|
|
46
|
+
delegationType: "user-to-agent" | "agent-to-subagent";
|
|
47
|
+
/** Harness the delegation was established under (audit aid). */
|
|
48
|
+
harness?: string;
|
|
49
|
+
/** Sub-agent type, present only for `agent-to-subagent`. */
|
|
50
|
+
subAgentType?: string;
|
|
51
|
+
/** ISO-8601 timestamp the delegation was stamped. */
|
|
52
|
+
delegatedAt: string;
|
|
53
|
+
}
|
|
33
54
|
export interface OryAgentDynamicCredentials {
|
|
34
55
|
/** Issued client_id. */
|
|
35
56
|
clientId: string;
|
|
@@ -45,6 +66,14 @@ export interface OryAgentDynamicCredentials {
|
|
|
45
66
|
projectUrl: string;
|
|
46
67
|
/** Harness name baked into the client_name (audit aid). */
|
|
47
68
|
harness?: string;
|
|
69
|
+
/**
|
|
70
|
+
* The delegation edge recorded for this client at registration. Persisted
|
|
71
|
+
* here in local config only — Ory's public DCR endpoint rejects a `metadata`
|
|
72
|
+
* field, so it is never stored server-side. Absent when the delegator wasn't
|
|
73
|
+
* known at registration time (e.g. DCR bootstrapped from an out-of-band
|
|
74
|
+
* initial access token with no user/agent principal).
|
|
75
|
+
*/
|
|
76
|
+
delegation?: OryDelegationRecord;
|
|
48
77
|
}
|
|
49
78
|
/** Credentials for the AI agent principal (machine identity). */
|
|
50
79
|
export interface OryAgentCredentialsBlock {
|
|
@@ -88,10 +117,26 @@ export interface OryPluginConfig {
|
|
|
88
117
|
* never be substituted for a slug when building it.
|
|
89
118
|
*/
|
|
90
119
|
projectId?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Human-readable project and workspace names, captured at install time for
|
|
122
|
+
* display only (e.g. the dashboard's connected-stack card). Not used to
|
|
123
|
+
* address any API — {@link projectUrl} / {@link projectId} do that.
|
|
124
|
+
*/
|
|
125
|
+
projectName?: string;
|
|
126
|
+
workspaceName?: string;
|
|
91
127
|
apiKey?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Token id of the project API key stored in {@link apiKey}, captured when the
|
|
130
|
+
* installer mints the key via the Ory Console API. Ory only returns a key's
|
|
131
|
+
* secret at creation and deletion addresses the token by id (not by its
|
|
132
|
+
* secret value), so the id is persisted here purely so `uninstall` can delete
|
|
133
|
+
* the key server-side. Absent for keys minted before id-tracking, or supplied
|
|
134
|
+
* by hand via `configure --api-key`.
|
|
135
|
+
*/
|
|
136
|
+
apiKeyId?: string;
|
|
92
137
|
/**
|
|
93
138
|
* Public OAuth2 client id used by the user PKCE browser flow when
|
|
94
|
-
*
|
|
139
|
+
* the interactive user login runs (every session). The client must be registered ahead of time
|
|
95
140
|
* in the Ory project with all four loopback redirect URIs
|
|
96
141
|
* (`http://127.0.0.1:47823..47826/callback`) and
|
|
97
142
|
* `token_endpoint_auth_method=none`. The local stack provisions one
|
|
@@ -107,14 +152,6 @@ export interface OryPluginConfig {
|
|
|
107
152
|
* tuple set is correct. See {@link PermissionMode}.
|
|
108
153
|
*/
|
|
109
154
|
permissionMode?: PermissionMode;
|
|
110
|
-
/**
|
|
111
|
-
* Whether the interactive user PKCE login runs at session start. When
|
|
112
|
-
* true, every session runs `ensureUserAuthenticated`; when unset the
|
|
113
|
-
* flow is a no-op. Set via `configure --user-login` / `--no-user-login`.
|
|
114
|
-
* The `ORY_USER_LOGIN` env var overrides this when set. Requires an
|
|
115
|
-
* OAuth2 client id ({@link oauth2ClientId}) to actually complete a login.
|
|
116
|
-
*/
|
|
117
|
-
userLogin?: boolean;
|
|
118
155
|
/**
|
|
119
156
|
* Permission-check subject namespace for the human user. When set, the
|
|
120
157
|
* user is addressed as a SubjectSet `<namespace>:<subject>` in permission
|
|
@@ -159,14 +196,6 @@ export declare function getConfigPath(): string;
|
|
|
159
196
|
* does not exist or is invalid.
|
|
160
197
|
*/
|
|
161
198
|
export declare function loadConfig(): OryPluginConfig;
|
|
162
|
-
/**
|
|
163
|
-
* Read `ORY_USER_LOGIN` from the environment. Returns `true`/`false` when
|
|
164
|
-
* the var is set (any recognized truthy value enables it; anything else
|
|
165
|
-
* disables it), or `undefined` when the var is absent/empty so callers
|
|
166
|
-
* fall back to the config file. Centralized here so the user gate, status
|
|
167
|
-
* CLI, and configure command resolve it identically.
|
|
168
|
-
*/
|
|
169
|
-
export declare function parseUserLoginEnv(): boolean | undefined;
|
|
170
199
|
/**
|
|
171
200
|
* Save config to the config file. Merges with existing values — only
|
|
172
201
|
* provided fields are overwritten. Concurrent processes serialize via a
|
|
@@ -209,13 +238,13 @@ export declare function looksLikeProjectId(value: string): boolean;
|
|
|
209
238
|
export declare function resolveConfig(): {
|
|
210
239
|
projectUrl?: string;
|
|
211
240
|
projectId?: string;
|
|
241
|
+
projectName?: string;
|
|
242
|
+
workspaceName?: string;
|
|
212
243
|
apiKey?: string;
|
|
213
244
|
oauth2ClientId?: string;
|
|
214
245
|
auditOnly: boolean;
|
|
215
246
|
permissionMode: PermissionMode;
|
|
216
247
|
permissionModeSource: "env" | "config" | "default";
|
|
217
|
-
userLogin: boolean;
|
|
218
|
-
userLoginSource: "env" | "config" | "default";
|
|
219
248
|
userSubjectNamespace?: string;
|
|
220
249
|
userSubjectNamespaceSource: "env" | "config" | "none";
|
|
221
250
|
projectUrlSource: "env" | "config" | "none";
|