@ory/argus 1.5.2 → 1.6.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/dist/testing.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * common assertion patterns so that harness plugin tests focus on
6
6
  * harness-specific behavior rather than duplicating boilerplate.
7
7
  */
8
- import { vi } from "vitest";
8
+ import { type Mock } from "vitest";
9
9
  import { OryAgentClient } from "./client.js";
10
10
  import type { ActivityEntry } from "./logger.js";
11
11
  import type { PermissionMode } from "./config.js";
@@ -13,8 +13,8 @@ export { runHarnessContractSuite, type HarnessContractAdapter, type ContractCont
13
13
  export interface SdkLazySessionContractAdapter {
14
14
  name: string;
15
15
  harness: string;
16
- createSessionStarterMock: ReturnType<typeof vi.fn>;
17
- ensureSessionMock: ReturnType<typeof vi.fn>;
16
+ createSessionStarterMock: Mock;
17
+ ensureSessionMock: Mock;
18
18
  createSubject(client: OryAgentClient, projectUrl?: string): {
19
19
  invoke(index: number): Promise<unknown>;
20
20
  };
@@ -40,7 +40,7 @@ export declare function createMockClient(overrides?: Partial<ConstructorParamete
40
40
  export declare function spyRecordDelegation(client: OryAgentClient, result?: {
41
41
  nodeId: string;
42
42
  delegationChain: string[];
43
- }): import("vitest").Mock<(input: import("./client.js").RecordDelegationInput, options?: {
43
+ }): Mock<(input: import("./client.js").RecordDelegationInput, options?: {
44
44
  fetchImpl?: typeof fetch;
45
45
  activityAttributes?: Record<string, unknown>;
46
46
  agentToken?: string;
@@ -52,7 +52,7 @@ export declare function spyRecordDelegation(client: OryAgentClient, result?: {
52
52
  * Stub an internal API instance method on the client.
53
53
  * Returns a vi.fn mock so callers can assert on calls.
54
54
  */
55
- export declare function stubApi<K extends "frontend" | "oauth2" | "permission">(client: OryAgentClient, api: K, method: string, impl: (...args: unknown[]) => unknown): ReturnType<typeof vi.fn>;
55
+ export declare function stubApi<K extends "frontend" | "oauth2" | "permission">(client: OryAgentClient, api: K, method: string, impl: (...args: unknown[]) => unknown): Mock;
56
56
  /** Successful session verification response (wraps Ory API shape). */
57
57
  export declare const MOCK_SESSION_RESPONSE: {
58
58
  data: {
@@ -76,7 +76,6 @@ export declare const MOCK_SESSION_RESPONSE: {
76
76
  /** Inactive session (same shape, active: false). */
77
77
  export declare const MOCK_INACTIVE_SESSION_RESPONSE: {
78
78
  data: {
79
- active: boolean;
80
79
  id: string;
81
80
  authenticated_at: string;
82
81
  expires_at: string;
@@ -91,6 +90,7 @@ export declare const MOCK_INACTIVE_SESSION_RESPONSE: {
91
90
  email: string;
92
91
  };
93
92
  };
93
+ active: boolean;
94
94
  };
95
95
  };
96
96
  /** Successful OAuth2 token introspection response. */
@@ -238,19 +238,19 @@ export declare function disconnectSecurity(which?: "neither" | "no-client-id" |
238
238
  */
239
239
  export declare function clearOryEnv(): void;
240
240
  /** Stub verifySession to succeed. */
241
- export declare function stubSessionSuccess(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
241
+ export declare function stubSessionSuccess(client: OryAgentClient): Mock;
242
242
  /** Stub verifySession to return inactive. */
243
- export declare function stubSessionInactive(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
243
+ export declare function stubSessionInactive(client: OryAgentClient): Mock;
244
244
  /** Stub verifySession to throw a network error. */
245
- export declare function stubSessionNetworkError(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
245
+ export declare function stubSessionNetworkError(client: OryAgentClient): Mock;
246
246
  /** Stub verifySession to throw MFA required. */
247
- export declare function stubSessionMfaRequired(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
247
+ export declare function stubSessionMfaRequired(client: OryAgentClient): Mock;
248
248
  /** Stub verifySession to throw session_inactive. */
249
- export declare function stubSessionExpired(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
249
+ export declare function stubSessionExpired(client: OryAgentClient): Mock;
250
250
  /** Stub introspectToken to succeed. */
251
- export declare function stubOAuth2Success(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
251
+ export declare function stubOAuth2Success(client: OryAgentClient): Mock;
252
252
  /** Stub introspectToken to return inactive. */
253
- export declare function stubOAuth2Inactive(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
253
+ export declare function stubOAuth2Inactive(client: OryAgentClient): Mock;
254
254
  /**
255
255
  * Set the mode the server-read stub reports. Also clears the in-memory
256
256
  * permission-mode cache so the new value takes effect immediately (tests run
@@ -258,26 +258,38 @@ export declare function stubOAuth2Inactive(client: OryAgentClient): import("vite
258
258
  */
259
259
  export declare function setTestPermissionMode(mode: PermissionMode): void;
260
260
  /** Stub checkPermission to allow. */
261
- export declare function stubPermissionAllowed(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable> & {
262
- batch: import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
261
+ export declare function stubPermissionAllowed(client: OryAgentClient): import("vitest").MockInstance<import("../../../node_modules/vitest/dist/chunks/config.d.QBNYCgFU.js", { with: { "resolution-mode": "import" } }).v> & {
262
+ (...args: any[]): any;
263
+ new (...args: any[]): any;
264
+ } & {} & {
265
+ batch: Mock;
263
266
  };
264
267
  /** Stub checkPermission to deny (the tool check; the mode check still answers `currentTestMode`). */
265
- export declare function stubPermissionDenied(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable> & {
266
- batch: import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
268
+ export declare function stubPermissionDenied(client: OryAgentClient): import("vitest").MockInstance<import("../../../node_modules/vitest/dist/chunks/config.d.QBNYCgFU.js", { with: { "resolution-mode": "import" } }).v> & {
269
+ (...args: any[]): any;
270
+ new (...args: any[]): any;
271
+ } & {} & {
272
+ batch: Mock;
267
273
  };
268
274
  /** Stub checkPermission to throw a network error. */
269
- export declare function stubPermissionNetworkError(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable> & {
270
- batch: import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
275
+ export declare function stubPermissionNetworkError(client: OryAgentClient): import("vitest").MockInstance<import("../../../node_modules/vitest/dist/chunks/config.d.QBNYCgFU.js", { with: { "resolution-mode": "import" } }).v> & {
276
+ (...args: any[]): any;
277
+ new (...args: any[]): any;
278
+ } & {} & {
279
+ batch: Mock;
271
280
  };
272
281
  /** Stub checkPermission to throw a rate-limit error. */
273
- export declare function stubPermissionRateLimited(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable> & {
274
- batch: import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
282
+ export declare function stubPermissionRateLimited(client: OryAgentClient): import("vitest").MockInstance<import("../../../node_modules/vitest/dist/chunks/config.d.QBNYCgFU.js", { with: { "resolution-mode": "import" } }).v> & {
283
+ (...args: any[]): any;
284
+ new (...args: any[]): any;
285
+ } & {} & {
286
+ batch: Mock;
275
287
  };
276
- /** Stub both checkPermission (server allow) and batchCheckPermission (both allow). */
277
- export declare function stubMcpAllowed(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
278
- /** Stub checkPermission to deny (server-only MCP check). */
279
- export declare function stubMcpServerDenied(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
280
- /** Stub batchCheckPermission: server allowed, tool denied. */
281
- export declare function stubMcpToolDenied(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
282
- /** Stub checkPermission to throw network error (MCP fail-open). */
283
- export declare function stubMcpNetworkError(client: OryAgentClient): import("vitest").Mock<import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Procedure | import(".pnpm/@vitest+spy@4.1.7/node_modules/@vitest/spy", { with: { "resolution-mode": "import" } }).Constructable>;
288
+ /** Stub MCP checks so the server and the tool are both allowed. */
289
+ export declare function stubMcpAllowed(client: OryAgentClient): Mock;
290
+ /** Stub MCP checks so the server is denied (No access). */
291
+ export declare function stubMcpServerDenied(client: OryAgentClient): Mock;
292
+ /** Stub MCP checks so the server is allowed but the tool is denied (its tier is blocked). */
293
+ export declare function stubMcpToolDenied(client: OryAgentClient): Mock;
294
+ /** Stub MCP checks to throw a network error (MCP fail-open). */
295
+ export declare function stubMcpNetworkError(client: OryAgentClient): Mock;
package/dist/testing.js CHANGED
@@ -553,25 +553,47 @@ function stubPermissionRateLimited(client) {
553
553
  return Object.assign(check, { batch });
554
554
  }
555
555
  // ─── MCP Stub Presets ─────────────────────────────────────────────
556
- /** Stub both checkPermission (server allow) and batchCheckPermission (both allow). */
557
- function stubMcpAllowed(client) {
556
+ /**
557
+ * Answer MCP gate checks tuple by tuple: the `McpServer` and `McpTool` use
558
+ * permits get the given answers, mode checks answer `currentTestMode`, block
559
+ * probes find no block, and any other use permit is allowed.
560
+ */
561
+ function stubMcpDecision(client, answers) {
558
562
  ensurePermissionCredential(client);
559
- stubApi(client, "permission", "checkPermission", checkPermissionResponder(exports.PERMISSION_ALLOWED));
560
- return stubApi(client, "permission", "batchCheckPermission", () => Promise.resolve(exports.BATCH_BOTH_ALLOWED));
563
+ const answer = (tuple) => {
564
+ if (tuple.object === opl_js_1.PERMISSION_MODE_OBJECT && tuple.relation === opl_js_1.RELATION_ENFORCED_SUBJECTS) {
565
+ return currentTestMode === "enforce";
566
+ }
567
+ if (tuple.relation === "blockedSubjects")
568
+ return false;
569
+ if (tuple.namespace === "McpServer")
570
+ return answers.server;
571
+ if (tuple.namespace === "McpTool")
572
+ return answers.tool;
573
+ return true;
574
+ };
575
+ stubApi(client, "permission", "checkPermission", (params) => Promise.resolve(answer(params) ? exports.PERMISSION_ALLOWED : exports.PERMISSION_DENIED));
576
+ return stubApi(client, "permission", "batchCheckPermission", (request) => {
577
+ const tuples = request
578
+ .batchCheckPermissionBody?.tuples ?? [];
579
+ return Promise.resolve({ data: { results: tuples.map((tuple) => ({ allowed: answer(tuple) })) } });
580
+ });
581
+ }
582
+ /** Stub MCP checks so the server and the tool are both allowed. */
583
+ function stubMcpAllowed(client) {
584
+ return stubMcpDecision(client, { server: true, tool: true });
561
585
  }
562
- /** Stub checkPermission to deny (server-only MCP check). */
586
+ /** Stub MCP checks so the server is denied (No access). */
563
587
  function stubMcpServerDenied(client) {
564
- ensurePermissionCredential(client);
565
- return stubApi(client, "permission", "checkPermission", checkPermissionResponder(exports.PERMISSION_DENIED));
588
+ return stubMcpDecision(client, { server: false, tool: true });
566
589
  }
567
- /** Stub batchCheckPermission: server allowed, tool denied. */
590
+ /** Stub MCP checks so the server is allowed but the tool is denied (its tier is blocked). */
568
591
  function stubMcpToolDenied(client) {
569
- ensurePermissionCredential(client);
570
- stubApi(client, "permission", "checkPermission", checkPermissionResponder(exports.PERMISSION_ALLOWED));
571
- return stubApi(client, "permission", "batchCheckPermission", () => Promise.resolve(exports.BATCH_SERVER_ALLOWED_TOOL_DENIED));
592
+ return stubMcpDecision(client, { server: true, tool: false });
572
593
  }
573
- /** Stub checkPermission to throw network error (MCP fail-open). */
594
+ /** Stub MCP checks to throw a network error (MCP fail-open). */
574
595
  function stubMcpNetworkError(client) {
575
596
  ensurePermissionCredential(client);
597
+ stubApi(client, "permission", "batchCheckPermission", () => Promise.reject(makeNetworkError()));
576
598
  return stubApi(client, "permission", "checkPermission", () => Promise.reject(makeNetworkError()));
577
599
  }
package/dist/types.d.ts CHANGED
@@ -32,6 +32,19 @@ export interface PermissionCheck {
32
32
  object: string;
33
33
  relation: string;
34
34
  };
35
+ /**
36
+ * The MCP server an `McpServer` or `McpTool` check targets, as the harness
37
+ * reported it. Agent Security resolves it to the catalog server it checks.
38
+ */
39
+ mcp?: McpServerHint;
40
+ }
41
+ export interface McpServerHint {
42
+ /** The server name as the harness reports it. */
43
+ server: string;
44
+ /** The MCP tool name as the server defines it. */
45
+ tool?: string;
46
+ /** Hashed server identifiers from {@link mcpServerFingerprints}. */
47
+ fingerprints?: string[];
35
48
  }
36
49
  export interface PermissionResult {
37
50
  allowed: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/argus",
3
- "version": "1.5.2",
3
+ "version": "1.6.0",
4
4
  "description": "Ory Argus: the core API for building authentication, authorization, and audit into AI agent harness plugins, extensions, and custom integrations",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ory.com",
@@ -62,10 +62,10 @@
62
62
  "!dist/**/*.tsbuildinfo"
63
63
  ],
64
64
  "dependencies": {
65
- "@ory/client": "^1.22.37",
65
+ "@ory/client": "^1.22.66",
66
66
  "@vscode/tree-sitter-wasm": "^0.3.1",
67
- "open": "^11.0.0",
68
- "web-tree-sitter": "^0.26.11"
67
+ "open": "^11.0.4",
68
+ "web-tree-sitter": "^0.27.1"
69
69
  },
70
70
  "engines": {
71
71
  "node": ">=22"