@ory/argus 0.14.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +31 -46
  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 +39 -91
  6. package/assets/skills/ory-e2b-sandbox/SKILL.md +18 -17
  7. package/assets/skills/ory-temporal-worker/SKILL.md +31 -33
  8. package/assets/skills/permissions-onboarding/SKILL.md +131 -104
  9. package/dist/adapters.d.ts +88 -32
  10. package/dist/adapters.js +443 -164
  11. package/dist/agent-auth.d.ts +226 -67
  12. package/dist/agent-auth.js +951 -205
  13. package/dist/auth-store.d.ts +37 -2
  14. package/dist/auth-store.js +37 -3
  15. package/dist/auth.d.ts +33 -4
  16. package/dist/auth.js +163 -20
  17. package/dist/bash-parser.d.ts +98 -0
  18. package/dist/bash-parser.js +396 -0
  19. package/dist/branding.d.ts +77 -16
  20. package/dist/branding.js +93 -23
  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 -239
  26. package/dist/client.d.ts +175 -138
  27. package/dist/client.js +672 -391
  28. package/dist/config.d.ts +217 -54
  29. package/dist/config.js +461 -42
  30. package/dist/context.d.ts +10 -0
  31. package/dist/context.js +21 -0
  32. package/dist/contract-suite.d.ts +3 -5
  33. package/dist/contract-suite.js +75 -47
  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 +28 -23
  47. package/dist/index.js +173 -58
  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.js +7 -7
  54. package/dist/local/index.d.ts +2 -2
  55. package/dist/local/index.js +24 -10
  56. package/dist/local/manager.d.ts +20 -1
  57. package/dist/local/manager.js +159 -36
  58. package/dist/local/ports.d.ts +158 -0
  59. package/dist/local/ports.js +443 -0
  60. package/dist/local/seed.d.ts +13 -5
  61. package/dist/local/seed.js +62 -38
  62. package/dist/logger.d.ts +54 -25
  63. package/dist/logger.js +329 -63
  64. package/dist/mcp.d.ts +2 -2
  65. package/dist/mcp.js +10 -5
  66. package/dist/mirror-bootstrap.d.ts +48 -0
  67. package/dist/mirror-bootstrap.js +254 -0
  68. package/dist/opl.d.ts +289 -0
  69. package/dist/opl.js +446 -0
  70. package/dist/permission-mode.d.ts +87 -0
  71. package/dist/permission-mode.js +307 -0
  72. package/dist/permissions-cli.d.ts +13 -49
  73. package/dist/permissions-cli.js +154 -348
  74. package/dist/permissions.d.ts +148 -38
  75. package/dist/permissions.js +591 -45
  76. package/dist/post-install.d.ts +33 -0
  77. package/dist/post-install.js +127 -0
  78. package/dist/read-credential.d.ts +65 -0
  79. package/dist/read-credential.js +86 -0
  80. package/dist/registry/cli.js +5 -2
  81. package/dist/registry/config.d.ts +0 -17
  82. package/dist/registry/config.js +0 -23
  83. package/dist/registry/index.d.ts +1 -1
  84. package/dist/registry/index.js +2 -2
  85. package/dist/registry/manager.d.ts +4 -21
  86. package/dist/registry/manager.js +21 -37
  87. package/dist/runtime-credential.d.ts +140 -0
  88. package/dist/runtime-credential.js +572 -0
  89. package/dist/runtime.d.ts +413 -0
  90. package/dist/runtime.js +825 -0
  91. package/dist/setup.d.ts +23 -47
  92. package/dist/setup.js +59 -116
  93. package/dist/skills.js +0 -7
  94. package/dist/status-cli.d.ts +27 -11
  95. package/dist/status-cli.js +121 -115
  96. package/dist/status-data.d.ts +116 -17
  97. package/dist/status-data.js +121 -38
  98. package/dist/subject.d.ts +126 -20
  99. package/dist/subject.js +215 -30
  100. package/dist/testing.d.ts +74 -38
  101. package/dist/testing.js +185 -68
  102. package/dist/tool-catalog.d.ts +53 -11
  103. package/dist/tool-catalog.js +164 -13
  104. package/dist/tool-metadata.d.ts +7 -6
  105. package/dist/tool-metadata.js +6 -5
  106. package/dist/types.d.ts +11 -1
  107. package/dist/uninstall.d.ts +71 -34
  108. package/dist/uninstall.js +217 -85
  109. package/dist/user-login.d.ts +9 -10
  110. package/dist/user-login.js +56 -75
  111. package/dist/watch-cli.d.ts +6 -0
  112. package/dist/watch-cli.js +217 -0
  113. package/package.json +4 -27
  114. package/assets/commands/dashboard.md +0 -34
  115. package/dist/dashboard-cli.d.ts +0 -8
  116. package/dist/dashboard-cli.js +0 -70
  117. package/dist/dev.d.ts +0 -103
  118. package/dist/dev.js +0 -583
  119. package/dist/interactive-setup.d.ts +0 -286
  120. package/dist/interactive-setup.js +0 -1734
  121. package/dist/local/jaeger-main.d.ts +0 -13
  122. package/dist/local/jaeger-main.js +0 -85
  123. package/dist/local/jaeger.d.ts +0 -50
  124. package/dist/local/jaeger.js +0 -162
  125. package/dist/otel/exporter.d.ts +0 -17
  126. package/dist/otel/exporter.js +0 -12
  127. package/dist/otel/index.d.ts +0 -2
  128. package/dist/otel/index.js +0 -8
  129. package/dist/otel/otlp.d.ts +0 -103
  130. package/dist/otel/otlp.js +0 -385
  131. package/dist/project-api-key.d.ts +0 -69
  132. package/dist/project-api-key.js +0 -147
  133. package/dist/setup-actions.d.ts +0 -232
  134. package/dist/setup-actions.js +0 -507
  135. package/dist/tracer.d.ts +0 -190
  136. package/dist/tracer.js +0 -481
  137. package/dist/watch-sandbox.d.ts +0 -9
  138. package/dist/watch-sandbox.js +0 -81
  139. package/dist/web/api.d.ts +0 -33
  140. package/dist/web/api.js +0 -294
  141. package/dist/web/launch.d.ts +0 -11
  142. package/dist/web/launch.js +0 -96
  143. package/dist/web/server.d.ts +0 -20
  144. package/dist/web/server.js +0 -233
  145. package/dist/web/types.d.ts +0 -65
  146. package/dist/web/types.js +0 -2
  147. package/dist/webapp/assets/index-Wucl4SZs.css +0 -1
  148. package/dist/webapp/assets/index-m-GtEdq0.js +0 -49
  149. package/dist/webapp/favicon.ico +0 -0
  150. package/dist/webapp/index.html +0 -15
package/dist/dev.d.ts DELETED
@@ -1,103 +0,0 @@
1
- import { type SeedResult } from "./local/seed.js";
2
- export interface InstallContext {
3
- /** Absolute path to the sandbox directory used as install/launch cwd. */
4
- sandboxDir: string;
5
- /**
6
- * Run `npm install <package>` inside the sandbox against the local registry.
7
- * Defaults the package name to `@ory/<harnessName>`.
8
- */
9
- npmInstall(packageName?: string): void;
10
- /**
11
- * Run `npx --package=<pkg> <bin> ...args` from the sandbox cwd against the
12
- * local registry. Defaults the package to `@ory/<harnessName>`
13
- * and the binary to the launcher's configured `binaryName` (or
14
- * `ory-<harnessName>` if not set).
15
- */
16
- npxCli(args: string[], opts?: {
17
- packageName?: string;
18
- binaryName?: string;
19
- }): void;
20
- }
21
- export interface DevLauncherConfig {
22
- /** Harness identifier — used for sandbox dir name and default package name, e.g. "claude-code" */
23
- harnessName: string;
24
- /** CLI command to launch, e.g. "claude", "codex", "gemini", "opencode" */
25
- command: string;
26
- /** Absolute path to the plugin package root (used to locate the workspace root) */
27
- packageRoot: string;
28
- /**
29
- * Default binary name for `npxCli` calls. Defaults to `ory-<harnessName>`.
30
- * Override when the plugin's published binary doesn't match the harness
31
- * directory name (e.g. claude-code exposes `ory-claude`, gemini-cli exposes
32
- * `ory-gemini`).
33
- */
34
- binaryName?: string;
35
- /**
36
- * Run the harness's documented install flow (the README's `npx ory-<harness> install`
37
- * commands) against the local registry. Each launcher invokes the install steps
38
- * appropriate for its harness — the launcher itself never hand-writes config files.
39
- */
40
- install(ctx: InstallContext): void;
41
- /** Extra tip lines to print before launch */
42
- extraTips?: string[];
43
- /**
44
- * Base args always passed to the harness binary at launch, prepended to any
45
- * args forwarded from the dev-launcher CLI. Use for dev-only flags a plugin
46
- * needs to exercise its hooks — e.g. Codex requires
47
- * `--dangerously-bypass-hook-trust` so freshly installed (untrusted) plugin
48
- * hooks run without the interactive trust prompt.
49
- */
50
- launchArgs?: string[];
51
- }
52
- /**
53
- * Parse the dev-launcher CLI args, splitting out launcher-only flags from the
54
- * args that should be forwarded to the harness binary.
55
- *
56
- * Launcher-only flags:
57
- * --no-local Opt out of the auto-managed local Ory stack (local Ory is
58
- * the default so multiple plugins can share one stack).
59
- * --fresh Wipe runtime state before launching: stop and remove the
60
- * local Ory stack, Verdaccio registry, and Jaeger container
61
- * (including their volumes and on-disk state), remove this
62
- * harness's sandbox dir, and delete the shared user config
63
- * dir. Build artifacts and node_modules are not touched —
64
- * use `pnpm clean:all` followed by `pnpm install` for that.
65
- */
66
- export declare function parseDevLauncherArgs(argv: readonly string[]): {
67
- noLocalFlag: boolean;
68
- freshFlag: boolean;
69
- forwardedArgs: string[];
70
- };
71
- /**
72
- * Decide whether the dev launcher should bring up a local Ory stack and seed
73
- * it for the harness to authenticate against. Local Ory is the default so
74
- * multiple harness plugins can share a single stack while developing — that
75
- * mimics the production case of many harnesses sharing one Ory deployment.
76
- *
77
- * Returns `false` only when the run was explicitly opted out, either via the
78
- * `--no-local` CLI flag or by setting `ORY_DEV_LOCAL` to a falsy value
79
- * (`0`, `false`, `no`, `off`).
80
- */
81
- export declare function isLocalOryEnabled(noLocalFlagPresent: boolean, envValue: string | undefined): boolean;
82
- /**
83
- * Run a dev launcher with the given configuration.
84
- *
85
- * Auto-starts the local Verdaccio registry, publishes the harness plugin
86
- * (with its workspace dependency closure) and `@ory/mcp-server`
87
- * to it, then invokes each plugin's documented install commands (the same
88
- * `npx ory-<harness> install` steps from the README) against the local
89
- * registry. The launcher itself never hand-writes harness config — the
90
- * plugin's own install logic is the source of truth.
91
- */
92
- export declare function runDevLauncher(config: DevLauncherConfig): Promise<void>;
93
- /**
94
- * Compose the harness env when local Ory is active. Wires up both
95
- * principals' credentials so the user gate runs real PKCE against local
96
- * Hydra and the agent gate runs RFC 7591 dynamic registration.
97
- *
98
- * The launcher always demonstrates the full UX — no opt-out into
99
- * env-token short-circuits. The user gate is forced on and the browser
100
- * flow fires every session against the seeded identity. Any pre-supplied
101
- * tokens leaking from the parent shell are explicitly cleared.
102
- */
103
- export declare function buildLocalOryEnv(gatewayUrl: string, seed: SeedResult): Record<string, string | undefined>;
package/dist/dev.js DELETED
@@ -1,583 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.parseDevLauncherArgs = parseDevLauncherArgs;
37
- exports.isLocalOryEnabled = isLocalOryEnabled;
38
- exports.runDevLauncher = runDevLauncher;
39
- exports.buildLocalOryEnv = buildLocalOryEnv;
40
- const crypto = __importStar(require("node:crypto"));
41
- const fs = __importStar(require("node:fs"));
42
- const path = __importStar(require("node:path"));
43
- const node_child_process_1 = require("node:child_process");
44
- const config_js_1 = require("./registry/config.js");
45
- const manager_js_1 = require("./registry/manager.js");
46
- const jaeger_js_1 = require("./local/jaeger.js");
47
- const manager_js_2 = require("./local/manager.js");
48
- const configs_js_1 = require("./local/configs.js");
49
- const seed_js_1 = require("./local/seed.js");
50
- const auth_store_js_1 = require("./auth-store.js");
51
- const config_js_2 = require("./config.js");
52
- const tracer_js_1 = require("./tracer.js");
53
- function ensureDir(dir) {
54
- if (!fs.existsSync(dir)) {
55
- fs.mkdirSync(dir, { recursive: true });
56
- }
57
- }
58
- function ensureSandboxManifest(sandboxDir, harnessName) {
59
- const manifestPath = path.join(sandboxDir, "package.json");
60
- if (fs.existsSync(manifestPath))
61
- return;
62
- fs.writeFileSync(manifestPath, JSON.stringify({ name: `ory-sandbox-${harnessName}`, private: true, version: "0.0.0" }, null, 2) + "\n");
63
- }
64
- function assertNpmAvailable() {
65
- const result = (0, node_child_process_1.spawnSync)("npm", ["--version"], { stdio: "ignore" });
66
- if (result.error || result.status !== 0) {
67
- throw new Error("`npm` is not on PATH. The dev launcher uses npm/npx to run each plugin's documented install commands.");
68
- }
69
- }
70
- function defaultBinaryName(harnessName) {
71
- return `ory-${harnessName}`;
72
- }
73
- /**
74
- * Parse the dev-launcher CLI args, splitting out launcher-only flags from the
75
- * args that should be forwarded to the harness binary.
76
- *
77
- * Launcher-only flags:
78
- * --no-local Opt out of the auto-managed local Ory stack (local Ory is
79
- * the default so multiple plugins can share one stack).
80
- * --fresh Wipe runtime state before launching: stop and remove the
81
- * local Ory stack, Verdaccio registry, and Jaeger container
82
- * (including their volumes and on-disk state), remove this
83
- * harness's sandbox dir, and delete the shared user config
84
- * dir. Build artifacts and node_modules are not touched —
85
- * use `pnpm clean:all` followed by `pnpm install` for that.
86
- */
87
- function parseDevLauncherArgs(argv) {
88
- let noLocalFlag = false;
89
- let freshFlag = false;
90
- const forwardedArgs = [];
91
- for (const arg of argv) {
92
- if (arg === "--no-local") {
93
- noLocalFlag = true;
94
- continue;
95
- }
96
- if (arg === "--fresh") {
97
- freshFlag = true;
98
- continue;
99
- }
100
- forwardedArgs.push(arg);
101
- }
102
- return { noLocalFlag, freshFlag, forwardedArgs };
103
- }
104
- /**
105
- * Decide whether the dev launcher should bring up a local Ory stack and seed
106
- * it for the harness to authenticate against. Local Ory is the default so
107
- * multiple harness plugins can share a single stack while developing — that
108
- * mimics the production case of many harnesses sharing one Ory deployment.
109
- *
110
- * Returns `false` only when the run was explicitly opted out, either via the
111
- * `--no-local` CLI flag or by setting `ORY_DEV_LOCAL` to a falsy value
112
- * (`0`, `false`, `no`, `off`).
113
- */
114
- function isLocalOryEnabled(noLocalFlagPresent, envValue) {
115
- if (noLocalFlagPresent)
116
- return false;
117
- if (envValue === undefined)
118
- return true;
119
- const v = envValue.trim().toLowerCase();
120
- if (v === "" || v === "0" || v === "false" || v === "no" || v === "off") {
121
- return false;
122
- }
123
- return true;
124
- }
125
- function npmEnv() {
126
- // Env shared by every install/runtime subprocess so npm/npx pulls from
127
- // the local registry through an isolated pacote cache, with the user's
128
- // supply-chain freshness gate disabled (otherwise just-published tarballs
129
- // get filtered out as `ENOVERSIONS — No versions available`).
130
- //
131
- // `npm_config_userconfig` swaps the userconfig file from `~/.npmrc` to a
132
- // launcher-managed npmrc that pins `@ory:registry` to the local Verdaccio.
133
- // Without this, a developer-level `@ory:registry=…` line in their own
134
- // `~/.npmrc` (left over from `npm login --scope=@ory` or similar) wins
135
- // against `--registry` for scoped packages and routes the launcher's
136
- // `npm install @ory/<harness>` — and the harness's own runtime `npx`
137
- // calls — back to npmjs.org. The symptoms are ENOVERSIONS or tarball
138
- // sha512 corruption depending on which side of the manifest/tarball
139
- // split each subprocess hits.
140
- return {
141
- ...process.env,
142
- npm_config_userconfig: (0, manager_js_1.ensureLauncherNpmrc)(),
143
- npm_config_registry: config_js_1.REGISTRY_URL,
144
- npm_config_cache: (0, manager_js_1.getLocalRegistryNpmCacheDir)(),
145
- npm_config_min_release_age: "0",
146
- };
147
- }
148
- function buildInstallContext(harnessName, sandboxDir, binaryName) {
149
- const defaultPackage = `@ory/${harnessName}`;
150
- const defaultBin = binaryName ?? defaultBinaryName(harnessName);
151
- return {
152
- sandboxDir,
153
- npmInstall(packageName = defaultPackage) {
154
- // npm 11's arborist crashes (`Cannot read properties of null (reading
155
- // 'matches')`) when running `npm install <pkg>` in a cwd that has no
156
- // `package.json`, so seed a minimal manifest before installing.
157
- ensureSandboxManifest(sandboxDir, harnessName);
158
- console.log(`[ory-dev] npm install ${packageName} (sandbox: ${sandboxDir})`);
159
- // `--min-release-age=0` must come from the CLI flag — config-file values
160
- // can't override a user-level `min-release-age` setting in npm 11.
161
- const result = (0, node_child_process_1.spawnSync)("npm", [
162
- "install",
163
- packageName,
164
- "--no-audit",
165
- "--no-fund",
166
- "--loglevel=error",
167
- "--min-release-age=0",
168
- "--save=false",
169
- ], { cwd: sandboxDir, stdio: "inherit", env: npmEnv() });
170
- if (result.status !== 0) {
171
- throw new Error(`npm install ${packageName} failed (exit ${result.status}).`);
172
- }
173
- },
174
- npxCli(args, opts = {}) {
175
- const packageName = opts.packageName ?? defaultPackage;
176
- const binaryName = opts.binaryName ?? defaultBin;
177
- // The dev launcher owns Ory configuration itself: it brings up (or
178
- // reuses) the local Ory stack, seeds identities, and wires the harness
179
- // env directly in `runDevLauncher`. The install CLI's interactive setup
180
- // wizard must not run here — it inherits the launcher's real TTY, so it
181
- // would prompt the developer and (on its local branch) try to stand up a
182
- // second Ory stack, colliding with the one the launcher bootstraps right
183
- // after. Force the wizard's `--no-configure` escape hatch on every
184
- // `install` invocation so the launcher's install step stays
185
- // non-interactive.
186
- const finalArgs = args[0] === "install" && !args.includes("--no-configure")
187
- ? [...args, "--no-configure"]
188
- : args;
189
- console.log(`[ory-dev] npx --package=${packageName} ${binaryName} ${finalArgs.join(" ")}`);
190
- const result = (0, node_child_process_1.spawnSync)("npx", [
191
- "--yes",
192
- `--package=${packageName}`,
193
- binaryName,
194
- ...finalArgs,
195
- ], { cwd: sandboxDir, stdio: "inherit", env: npmEnv() });
196
- if (result.status !== 0) {
197
- throw new Error(`npx --package=${packageName} ${binaryName} ${finalArgs.join(" ")} failed (exit ${result.status}).`);
198
- }
199
- },
200
- };
201
- }
202
- /**
203
- * Wipe all runtime state the launcher can safely reset without breaking the
204
- * running process: docker containers + volumes for the local Ory stack,
205
- * Verdaccio registry, and Jaeger; the on-disk `.sandbox/<harness>` and
206
- * `.ory-dev/` directories; and the shared user config dir. Build artifacts
207
- * and node_modules are out of scope — those require a separate
208
- * `pnpm clean:all && pnpm install`.
209
- *
210
- * Every step is best-effort: any failure is logged as a warning and the
211
- * reset continues. The launcher then re-bootstraps everything from scratch.
212
- */
213
- async function performFreshReset(sandbox) {
214
- console.log("[ory-dev] --fresh: wiping runtime state...");
215
- try {
216
- await (0, manager_js_2.localReset)();
217
- }
218
- catch (err) {
219
- const msg = err instanceof Error ? err.message : String(err);
220
- console.warn(`[ory-dev] --fresh: local Ory reset failed: ${msg}. Continuing.`);
221
- }
222
- try {
223
- await (0, manager_js_1.registryClean)();
224
- }
225
- catch (err) {
226
- const msg = err instanceof Error ? err.message : String(err);
227
- console.warn(`[ory-dev] --fresh: registry clean failed: ${msg}. Continuing.`);
228
- }
229
- const jaegerResult = (0, jaeger_js_1.stopDevJaeger)();
230
- if (jaegerResult.status === "error") {
231
- console.warn(`[ory-dev] --fresh: Jaeger stop failed: ${jaegerResult.detail ?? "unknown"}. Continuing.`);
232
- }
233
- if (fs.existsSync(sandbox)) {
234
- fs.rmSync(sandbox, { recursive: true, force: true });
235
- console.log(`[ory-dev] --fresh: removed ${sandbox}`);
236
- }
237
- const dataDir = (0, config_js_2.getDataDir)();
238
- if (fs.existsSync(dataDir)) {
239
- fs.rmSync(dataDir, { recursive: true, force: true });
240
- console.log(`[ory-dev] --fresh: removed ${dataDir}`);
241
- }
242
- console.log("[ory-dev] --fresh: reset complete.");
243
- }
244
- /**
245
- * Run a dev launcher with the given configuration.
246
- *
247
- * Auto-starts the local Verdaccio registry, publishes the harness plugin
248
- * (with its workspace dependency closure) and `@ory/mcp-server`
249
- * to it, then invokes each plugin's documented install commands (the same
250
- * `npx ory-<harness> install` steps from the README) against the local
251
- * registry. The launcher itself never hand-writes harness config — the
252
- * plugin's own install logic is the source of truth.
253
- */
254
- async function runDevLauncher(config) {
255
- const workspaceRoot = path.resolve(config.packageRoot, "..", "..");
256
- const sandbox = path.resolve(workspaceRoot, ".sandbox", config.harnessName);
257
- const localOryDir = path.resolve(workspaceRoot, ".ory-dev", "ory");
258
- const logFile = path.resolve(sandbox, "ory-agent-debug.log");
259
- const traceFile = path.resolve(sandbox, "ory-agent-trace.ndjson");
260
- const { noLocalFlag, freshFlag, forwardedArgs } = parseDevLauncherArgs(process.argv.slice(2));
261
- const localEnabled = isLocalOryEnabled(noLocalFlag, process.env.ORY_DEV_LOCAL);
262
- if (freshFlag) {
263
- await performFreshReset(sandbox);
264
- }
265
- // Belt-and-suspenders: each dev launch is the sole owner of its
266
- // session, so a stale pkce-flight lock from a previous run that died
267
- // mid-flow (browser closed, harness crashed, login UI 404'd, etc.)
268
- // would only block the next launch. Sweep it. The in-process gate's
269
- // own staleness check would catch this within 5 minutes, but the
270
- // explicit sweep makes the dev loop tight.
271
- if ((0, auth_store_js_1.clearPkceFlightLock)()) {
272
- console.log("[ory-dev] Cleared stale PKCE flight lock from a previous run.");
273
- }
274
- // Local dev demonstrates the full interactive PKCE browser login on every
275
- // launch. `buildLocalOryEnv` already clears env-supplied tokens, but a
276
- // still-valid *persisted* token from a prior run would short-circuit
277
- // `ensureUserAuthenticated` (mode "ok", "Re-using persisted access token")
278
- // so no browser prompt appears. Drop persisted user tokens too, so each
279
- // local launch reliably fires the login. Runs only in local-Ory mode — when
280
- // pointed at a real project (`ORY_DEV_LOCAL=0`), persisted tokens are kept.
281
- if (localEnabled) {
282
- (0, auth_store_js_1.clearTokens)();
283
- }
284
- assertNpmAvailable();
285
- console.log(`[ory-dev] Ensuring local npm registry is running...`);
286
- await (0, manager_js_1.ensureRegistryRunning)();
287
- console.log(`[ory-dev] Publishing @ory/${config.harnessName} (and mcp-server) to ${config_js_1.REGISTRY_URL}...`);
288
- await (0, manager_js_1.publishHarnessToLocal)(config.harnessName);
289
- ensureDir(sandbox);
290
- console.log(`[ory-dev] Running install flow for @ory/${config.harnessName}...`);
291
- const ctx = buildInstallContext(config.harnessName, sandbox, config.binaryName);
292
- config.install(ctx);
293
- // Each dev launch gets a fresh unique session subject so traces/permission
294
- // checks are distinguishable across runs. Used as the harness's
295
- // ORY_AGENT_SUBJECT_ID unless local-Ory mode supplies a real seeded session.
296
- const sessionName = `ory-sandbox-${crypto.randomBytes(6).toString("hex")}`;
297
- // When the user opts into local Ory, bring the docker stack up (or reuse
298
- // it) and seed two identities (agent + user). The harness env is then
299
- // wired so the user gate runs real browser PKCE against local Hydra and
300
- // the agent gate runs RFC 7591 dynamic client registration.
301
- const localOry = localEnabled
302
- ? await bootstrapLocalOry(localOryDir)
303
- : { active: false };
304
- console.log(`[ory-dev] Launching ${config.harnessName} with Ory plugin...`);
305
- console.log(`[ory-dev] Sandbox: ${sandbox}`);
306
- if (localOry.active) {
307
- const seed = localOry.seed;
308
- console.log("");
309
- console.log("[ory-dev] ──────────────────────────────────────────────────");
310
- console.log(`[ory-dev] Local Ory ready.`);
311
- console.log(`[ory-dev] API gateway: ${localOry.gatewayUrl}`);
312
- console.log(`[ory-dev] Console: ${configs_js_1.CONSOLE_URL}`);
313
- console.log(`[ory-dev] Jaeger: ${configs_js_1.JAEGER_UI_URL}`);
314
- console.log(`[ory-dev]`);
315
- console.log(`[ory-dev] When the browser opens for login, sign in as:`);
316
- console.log(`[ory-dev] email: ${seed.user.identity.email}`);
317
- console.log(`[ory-dev] password: ${seed.user.password}`);
318
- console.log("[ory-dev] ──────────────────────────────────────────────────");
319
- console.log("");
320
- }
321
- else {
322
- console.log(`[ory-dev] Session: ${sessionName}`);
323
- }
324
- console.log(`[ory-dev] Debug log: ${logFile}`);
325
- console.log(`[ory-dev] Trace file: ${traceFile}`);
326
- console.log(`[ory-dev] npm registry: ${config_js_1.REGISTRY_URL} (local)`);
327
- if (config.extraTips) {
328
- for (const tip of config.extraTips) {
329
- console.log(`[ory-dev] ${tip}`);
330
- }
331
- }
332
- const otelEndpoint = await resolveOtelEndpoint();
333
- if (otelEndpoint) {
334
- console.log(`[ory-dev] OTLP endpoint: ${otelEndpoint}`);
335
- }
336
- console.log(`[ory-dev] Tip: tail -f ${logFile} | jq . — live debug log`);
337
- console.log(`[ory-dev] Tip: pnpm watch:traces ${config.harnessName} — live trace stream\n`);
338
- const env = {
339
- ...npmEnv(),
340
- ORY_AGENT_DEBUG: "true",
341
- ORY_AGENT_LOG_FILE: logFile,
342
- ORY_AGENT_TRACE_FILE: traceFile,
343
- ...(localOry.active
344
- ? buildLocalOryEnv(localOry.gatewayUrl, localOry.seed)
345
- : { ORY_AGENT_SUBJECT_ID: sessionName }),
346
- ...(otelEndpoint
347
- ? buildOtelEnv(otelEndpoint, config.harnessName)
348
- : {}),
349
- };
350
- const launchArgs = [...(config.launchArgs ?? []), ...forwardedArgs];
351
- const result = (0, node_child_process_1.spawnSync)(config.command, launchArgs, {
352
- cwd: sandbox,
353
- stdio: "inherit",
354
- env,
355
- });
356
- printTraceSummary(traceFile);
357
- process.exit(result.status ?? 0);
358
- }
359
- function printTraceSummary(traceFile) {
360
- if (!fs.existsSync(traceFile))
361
- return;
362
- const raw = fs.readFileSync(traceFile, "utf8").trim();
363
- if (!raw)
364
- return;
365
- const lines = raw.split("\n").filter(Boolean);
366
- const spans = [];
367
- for (const line of lines) {
368
- try {
369
- spans.push(JSON.parse(line));
370
- }
371
- catch {
372
- /* skip malformed lines */
373
- }
374
- }
375
- if (spans.length === 0)
376
- return;
377
- console.log("");
378
- console.log(`[ory-dev] Trace summary — ${spans.length} span(s) recorded`);
379
- console.log(`[ory-dev] File: ${traceFile}`);
380
- const counts = new Map();
381
- const statusCounts = new Map();
382
- for (const span of spans) {
383
- const key = `${span.event}:${span.status}`;
384
- counts.set(key, (counts.get(key) ?? 0) + 1);
385
- statusCounts.set(span.status, (statusCounts.get(span.status) ?? 0) + 1);
386
- }
387
- console.log("[ory-dev] By status:");
388
- for (const [status, n] of statusCounts) {
389
- console.log(` ${status.padEnd(8)} ${n}`);
390
- }
391
- console.log("[ory-dev] By event:");
392
- const eventTotals = new Map();
393
- for (const span of spans) {
394
- eventTotals.set(span.event, (eventTotals.get(span.event) ?? 0) + 1);
395
- }
396
- const sortedEvents = [...eventTotals.entries()].sort((a, b) => b[1] - a[1]);
397
- for (const [event, n] of sortedEvents) {
398
- console.log(` ${event.padEnd(22)} ${n}`);
399
- }
400
- const tail = spans.slice(-10);
401
- console.log(`[ory-dev] Last ${tail.length} span(s):`);
402
- for (const span of tail) {
403
- console.log(" " + (0, tracer_js_1.formatSpan)(span));
404
- }
405
- }
406
- /**
407
- * Compose the harness env when local Ory is active. Wires up both
408
- * principals' credentials so the user gate runs real PKCE against local
409
- * Hydra and the agent gate runs RFC 7591 dynamic registration.
410
- *
411
- * The launcher always demonstrates the full UX — no opt-out into
412
- * env-token short-circuits. The user gate is forced on and the browser
413
- * flow fires every session against the seeded identity. Any pre-supplied
414
- * tokens leaking from the parent shell are explicitly cleared.
415
- */
416
- function buildLocalOryEnv(gatewayUrl, seed) {
417
- return {
418
- ORY_PROJECT_URL: gatewayUrl,
419
- ORY_PERMISSION_NAMESPACE: seed.permissions.namespace,
420
- // User login runs every session (always on); no flag needed. The launcher
421
- // demonstrates the interactive PKCE login UX end-to-end.
422
- // Agent identity — the harness self-registers via DCR on first run
423
- // using the user's bearer as the initial access token. No static
424
- // client_credentials are seeded; explicitly clear them so a leaking
425
- // shell env doesn't preempt the DCR path.
426
- ORY_AGENT_CLIENT_ID: undefined,
427
- ORY_AGENT_CLIENT_SECRET: undefined,
428
- ORY_AGENT_API_KEY: undefined,
429
- ORY_AGENT_REGISTRATION_TOKEN: undefined,
430
- // User identity — the OAuth2 client used by the PKCE browser flow.
431
- // Subject is the bare Kratos identity UUID; the User namespace pairs
432
- // with it to form the SubjectSet `User:<id>` the seed writes.
433
- ORY_OAUTH2_CLIENT_ID: seed.user.client.clientId,
434
- ORY_USER_SUBJECT_NAMESPACE: "User",
435
- ORY_USER_SUBJECT_ID: seed.user.identity.id,
436
- // Pre-supplied tokens would short-circuit the gate. Always clear
437
- // them so the launcher exercises the full PKCE flow.
438
- ORY_USER_SESSION_TOKEN: undefined,
439
- ORY_USER_OAUTH2_TOKEN: undefined,
440
- ORY_API_KEY: undefined,
441
- ORY_SESSION_TOKEN: undefined,
442
- ORY_OAUTH2_TOKEN: undefined,
443
- };
444
- }
445
- /**
446
- * Bring up the local Ory docker stack (Kratos + Keto + Hydra + nginx) and
447
- * seed a fresh test identity, returning the gateway URL and seed result so
448
- * the launcher can wire ORY_PROJECT_URL + ORY_SESSION_TOKEN into the harness
449
- * env.
450
- *
451
- * Fail-back-with-warning: any failure (Docker missing, compose error, gateway
452
- * unhealthy, seed error) is logged and the launcher continues without local
453
- * Ory. The harness still launches, and the plugin runs in pass-through mode.
454
- */
455
- async function bootstrapLocalOry(localDir) {
456
- console.log("[ory-dev] Local Ory: ensuring docker stack is up...");
457
- let stack;
458
- try {
459
- stack = await (0, manager_js_2.ensureLocalOryStack)({ quiet: true, localDir });
460
- }
461
- catch (err) {
462
- const msg = err instanceof Error ? err.message : String(err);
463
- console.warn(`[ory-dev] Local Ory bootstrap failed: ${msg}. Continuing without local Ory.`);
464
- return { active: false };
465
- }
466
- switch (stack.status) {
467
- case "already-running":
468
- console.log(`[ory-dev] Local Ory: stack already running at ${stack.gatewayUrl} — reusing.`);
469
- break;
470
- case "started":
471
- console.log(`[ory-dev] Local Ory: stack started at ${stack.gatewayUrl}.`);
472
- break;
473
- case "skipped:no-docker":
474
- console.warn(`[ory-dev] Local Ory: ${stack.detail ?? "Docker unavailable."} ` +
475
- `Continuing without local Ory.`);
476
- return { active: false };
477
- case "console-misconfigured":
478
- console.warn(`[ory-dev] Local Ory: ${stack.detail ?? "console misconfigured."} ` +
479
- `Continuing without local Ory.`);
480
- return { active: false };
481
- case "compose-failed":
482
- case "gateway-unhealthy":
483
- console.warn(`[ory-dev] Local Ory: ${stack.detail ?? stack.status}. ` +
484
- `Inspect logs with: cd ${stack.localDir} && docker compose logs. ` +
485
- `Continuing without local Ory.`);
486
- return { active: false };
487
- }
488
- const gatewayUrl = stack.gatewayUrl ?? "http://localhost:4000";
489
- const namespace = process.env.ORY_PERMISSION_NAMESPACE ?? "AgentTools";
490
- console.log("[ory-dev] Local Ory: seeding test identity + permissions...");
491
- let seed;
492
- try {
493
- seed = await (0, seed_js_1.seedLocalEnvironment)(namespace);
494
- }
495
- catch (err) {
496
- const msg = err instanceof Error ? err.message : String(err);
497
- console.warn(`[ory-dev] Local Ory: seed failed (${msg}). Continuing without local Ory.`);
498
- return { active: false };
499
- }
500
- console.log(`[ory-dev] Local Ory: user ${seed.user.identity.email}, ` +
501
- `${seed.permissions.tuples} permissions in '${namespace}' for ${seed.permissions.subject}.`);
502
- return { active: true, gatewayUrl, seed };
503
- }
504
- /**
505
- * OTel env vars the dev launcher propagates into the harness child. Each
506
- * entry pairs the standard `OTEL_*` name with its `ORY_OTLP_*` alias; the
507
- * alias is set in lockstep so harnesses (notably Claude Code) that sanitize
508
- * `OTEL_*` out of the hook-subprocess env still receive the configuration.
509
- *
510
- * Keep this list in sync with `ORY_ENV_ALIAS` in
511
- * `packages/core/src/otel/otlp.ts` — the exporter consults the same aliases
512
- * on the read side.
513
- */
514
- const OTEL_FORWARDED_VARS = [
515
- ["OTEL_EXPORTER_OTLP_ENDPOINT", "ORY_OTLP_ENDPOINT"],
516
- ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "ORY_OTLP_TRACES_ENDPOINT"],
517
- ["OTEL_EXPORTER_OTLP_HEADERS", "ORY_OTLP_HEADERS"],
518
- ["OTEL_EXPORTER_OTLP_TRACES_HEADERS", "ORY_OTLP_TRACES_HEADERS"],
519
- ["OTEL_EXPORTER_OTLP_PROTOCOL", "ORY_OTLP_PROTOCOL"],
520
- ["OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "ORY_OTLP_TRACES_PROTOCOL"],
521
- ["OTEL_SERVICE_NAME", "ORY_OTLP_SERVICE_NAME"],
522
- ["OTEL_RESOURCE_ATTRIBUTES", "ORY_OTLP_RESOURCE_ATTRIBUTES"],
523
- ];
524
- /**
525
- * Compose the OTLP env block for the harness child process. The resolved
526
- * endpoint is always written under both `OTEL_EXPORTER_OTLP_ENDPOINT` and
527
- * `ORY_OTLP_ENDPOINT`; every other OTel knob inherited from the parent
528
- * shell (and `OTEL_SERVICE_NAME`, which we default when unset) is mirrored
529
- * to its `ORY_OTLP_*` alias on the way through.
530
- */
531
- function buildOtelEnv(endpoint, harnessName) {
532
- const out = {};
533
- const defaults = {
534
- OTEL_EXPORTER_OTLP_ENDPOINT: endpoint,
535
- OTEL_SERVICE_NAME: process.env.OTEL_SERVICE_NAME ?? `ory-agent-plugin-${harnessName}`,
536
- };
537
- for (const [standardName, aliasName] of OTEL_FORWARDED_VARS) {
538
- const value = defaults[standardName] ?? process.env[standardName];
539
- if (!value)
540
- continue;
541
- out[standardName] = value;
542
- out[aliasName] = value;
543
- }
544
- return out;
545
- }
546
- /**
547
- * Determine the OTLP endpoint for the dev launch:
548
- * 1. Honor OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
549
- * (or their ORY_OTLP_* aliases) from the parent shell (Honeycomb,
550
- * custom collector, etc.).
551
- * 2. Otherwise auto-launch a local Jaeger container and use it. If Jaeger
552
- * is already reachable (from `local up` or a prior dev launch), reuse
553
- * it without spawning another container.
554
- * 3. Otherwise return undefined (file-based traces only) — e.g. when
555
- * Docker is not available on this machine.
556
- */
557
- async function resolveOtelEndpoint() {
558
- const fromEnv = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ??
559
- process.env.OTEL_EXPORTER_OTLP_ENDPOINT ??
560
- process.env.ORY_OTLP_TRACES_ENDPOINT ??
561
- process.env.ORY_OTLP_ENDPOINT;
562
- if (fromEnv)
563
- return fromEnv;
564
- console.log("[ory-dev] Ensuring Jaeger is running for trace viewing...");
565
- const result = await (0, jaeger_js_1.ensureDevJaeger)();
566
- switch (result.status) {
567
- case "already-running":
568
- console.log(`[ory-dev] Jaeger reachable (UI: ${result.uiUrl}) — reusing existing container.`);
569
- return result.endpoint;
570
- case "started":
571
- console.log(`[ory-dev] Jaeger started in Docker (UI: ${result.uiUrl}). Run 'pnpm jaeger:down' to stop it.`);
572
- return result.endpoint;
573
- case "skipped:no-docker":
574
- console.log(`[ory-dev] ${result.detail ?? "Docker not available."} Falling back to NDJSON traces only.`);
575
- return undefined;
576
- case "skipped:probe-failed":
577
- console.log(`[ory-dev] ${result.detail ?? "Jaeger did not become healthy in time."} Falling back to NDJSON traces only.`);
578
- return undefined;
579
- case "error":
580
- console.log(`[ory-dev] Jaeger auto-start failed: ${result.detail ?? "unknown error"}. Falling back to NDJSON traces only.`);
581
- return undefined;
582
- }
583
- }