@xemahq/authorization-internal-api-client 0.4.28 → 0.5.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.
@@ -1,11 +1,21 @@
1
1
  /**
2
2
  * Configurable fetch wrapper for Orval-generated clients.
3
3
  *
4
- * GENERATED by `@xemahq/api-client-generator` — do not edit. Every client in
5
- * the fleet ships this file byte-for-byte; a local edit is erased by the next
6
- * `pnpm refresh` and, until then, makes this one client speak to the platform
7
- * differently from all of its siblings. Change the template instead:
8
- * `api-client-generator/src/lib/custom-fetch-template.ts`.
4
+ * AUTO-GENERATED by `@xemahq/api-client-generator` — DO NOT EDIT. Every client
5
+ * in the fleet ships this file byte-for-byte; a hand edit is erased by the next
6
+ * regeneration and, until then, makes this one client speak to the platform
7
+ * differently from all of its siblings.
8
+ *
9
+ * Canonical source: `CANONICAL_CUSTOM_FETCH` in
10
+ * `packages/sdks/api-client-generator/src/lib/custom-fetch-template.ts`
11
+ * (repository `xema-kernel-sdk`). Change it there.
12
+ *
13
+ * Regenerate, from the root of THIS repository:
14
+ * pnpm --filter <owning-service> run openapi
15
+ * pnpm --filter <owning-service> run client:generate
16
+ * A mirror of this client under `xema-host-web` is not regenerated there: it
17
+ * is written by the frontend bridge, `tooling/frontend-bridge` in the
18
+ * xema-monorepo aggregator.
9
19
  *
10
20
  * Consumers must call `configureClient()` before using any endpoint function.
11
21
  * The baseUrl is prepended to the relative paths generated by Orval.
@@ -31,6 +41,21 @@ export interface RetryNotice {
31
41
  /** HTTP method being re-requested. */
32
42
  method: string;
33
43
  }
44
+ /**
45
+ * Per-request context handed to the callbacks this transport awaits BEFORE it
46
+ * sends the request.
47
+ *
48
+ * `signal` is the request's own `AbortSignal` (`options.signal`). It is the
49
+ * CALLER's cancellation: a callback may use it to stop work that is private to
50
+ * this request, but a callback serving several requests from one shared,
51
+ * single-flight acquisition (a token refresh) must NOT abort that shared work
52
+ * because one caller stopped — every other caller waiting on it would fail.
53
+ * The transport stops WAITING on its own regardless, so a callback that
54
+ * ignores the signal still cannot hold an aborted request.
55
+ */
56
+ export interface ClientCallbackOptions {
57
+ signal?: AbortSignal;
58
+ }
34
59
  export interface ClientConfig {
35
60
  /**
36
61
  * Static base URL (e.g. 'http://localhost:3140') — no trailing slash.
@@ -42,9 +67,13 @@ export interface ClientConfig {
42
67
  * the service registry on EVERY request (boot-order-safe). Wired by
43
68
  * `configureOrvalClientResolved` from `@xemahq/platform-common`.
44
69
  */
45
- baseUrlResolver?: () => string | Promise<string>;
46
- /** Optional async callback to get an auth token. Auto-sets Authorization header on every request. */
47
- getAuthToken?: () => Promise<string>;
70
+ baseUrlResolver?: (options?: ClientCallbackOptions) => string | Promise<string>;
71
+ /**
72
+ * Optional async callback to get an auth token. Auto-sets Authorization
73
+ * header on every request. Receives the request's signal — see
74
+ * {@link ClientCallbackOptions} for what it may and may not abort.
75
+ */
76
+ getAuthToken?: (options?: ClientCallbackOptions) => Promise<string>;
48
77
  /** Optional callback returning headers to inject on every request. Per-call headers take precedence. */
49
78
  getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
50
79
  /**
@@ -97,6 +126,7 @@ export declare class ClientError extends Error {
97
126
  readonly url: string;
98
127
  readonly body: unknown;
99
128
  constructor(status: number, url: string, body: unknown);
129
+ static [Symbol.hasInstance](candidate: unknown): boolean;
100
130
  }
101
131
  export declare function configureClient(config: ClientConfig): void;
102
132
  export declare function getClientConfig(): ClientConfig;
@@ -2,11 +2,21 @@
2
2
  /**
3
3
  * Configurable fetch wrapper for Orval-generated clients.
4
4
  *
5
- * GENERATED by `@xemahq/api-client-generator` — do not edit. Every client in
6
- * the fleet ships this file byte-for-byte; a local edit is erased by the next
7
- * `pnpm refresh` and, until then, makes this one client speak to the platform
8
- * differently from all of its siblings. Change the template instead:
9
- * `api-client-generator/src/lib/custom-fetch-template.ts`.
5
+ * AUTO-GENERATED by `@xemahq/api-client-generator` — DO NOT EDIT. Every client
6
+ * in the fleet ships this file byte-for-byte; a hand edit is erased by the next
7
+ * regeneration and, until then, makes this one client speak to the platform
8
+ * differently from all of its siblings.
9
+ *
10
+ * Canonical source: `CANONICAL_CUSTOM_FETCH` in
11
+ * `packages/sdks/api-client-generator/src/lib/custom-fetch-template.ts`
12
+ * (repository `xema-kernel-sdk`). Change it there.
13
+ *
14
+ * Regenerate, from the root of THIS repository:
15
+ * pnpm --filter <owning-service> run openapi
16
+ * pnpm --filter <owning-service> run client:generate
17
+ * A mirror of this client under `xema-host-web` is not regenerated there: it
18
+ * is written by the frontend bridge, `tooling/frontend-bridge` in the
19
+ * xema-monorepo aggregator.
10
20
  *
11
21
  * Consumers must call `configureClient()` before using any endpoint function.
12
22
  * The baseUrl is prepended to the relative paths generated by Orval.
@@ -19,6 +29,50 @@ Object.defineProperty(exports, "__esModule", { value: true });
19
29
  exports.customFetch = exports.ClientError = void 0;
20
30
  exports.configureClient = configureClient;
21
31
  exports.getClientConfig = getClientConfig;
32
+ /**
33
+ * Cross-package identity for `ClientError`.
34
+ *
35
+ * ── THE OUTAGE THIS IS FOR ────────────────────────────────────────────────
36
+ *
37
+ * PRODUCTION, 2026-09-22. A session launch aborted on
38
+ * `HTTP 503 from http://skill-registry-api…/skills`. A 503 is the archetypal
39
+ * TRANSIENT — agent-session's launch taxonomy already listed it as retryable —
40
+ * but it was classified PERMANENT and the launch was abandoned.
41
+ *
42
+ * The cause was this file. Every generated client package gets its OWN copy of
43
+ * `ClientError`, so there are as many classes as there are clients (81 at the
44
+ * time of writing), all byte-identical and all DIFFERENT OBJECTS. A consumer
45
+ * naturally writes `err instanceof ClientError` against the one client it
46
+ * imported — which reads as obviously correct and is silently package-local. An
47
+ * error from any OTHER client fails it, falls past every status check, and lands
48
+ * on whatever the default is.
49
+ *
50
+ * That was not the first time: biome-host had already switched to structural
51
+ * detection for the same reason, and canopy imports TWO `ClientError` classes
52
+ * and tests both. Three more call sites elsewhere carry the same shape.
53
+ *
54
+ * ── WHY A BRAND AND NOT A SHARED PACKAGE ─────────────────────────────────
55
+ *
56
+ * The obvious fix is one shared runtime class every client imports. It was
57
+ * rejected on measurement: the 81 generated clients are DEPENDENCY-FREE by
58
+ * design (exactly one has any dependency at all), and a shared class would have
59
+ * to be a PEER dependency to be safe — a normal dependency can be installed
60
+ * twice under version skew, which reinstates this identical bug in a form that
61
+ * is HARDER to see, because the classes then look like they ought to match.
62
+ *
63
+ * `Symbol.for` is a process-wide registry keyed by STRING, so every copy of
64
+ * this template resolves the same symbol without importing anything. The brand
65
+ * costs no dependency, cannot skew, and needs no new package.
66
+ *
67
+ * `Symbol.hasInstance` then makes plain `instanceof` mean the right thing
68
+ * fleet-wide: an error from ANY generated client satisfies `instanceof
69
+ * ClientError` in ANY other. A helper would have made the safe pattern
70
+ * available; this makes the dangerous pattern impossible.
71
+ *
72
+ * Narrow on purpose — the brand is set only by this constructor, so an unrelated
73
+ * error carrying a `status` is not admitted.
74
+ */
75
+ const CLIENT_ERROR_BRAND = Symbol.for('xema.generatedClientError');
22
76
  class ClientError extends Error {
23
77
  status;
24
78
  url;
@@ -29,10 +83,67 @@ class ClientError extends Error {
29
83
  this.url = url;
30
84
  this.body = body;
31
85
  this.name = 'ClientError';
86
+ // Non-enumerable: it must not appear in JSON, logs or snapshots — it is an
87
+ // identity marker, not payload.
88
+ Object.defineProperty(this, CLIENT_ERROR_BRAND, { value: true });
89
+ }
90
+ // `override` because the member shadows `Function.prototype[Symbol.hasInstance]`,
91
+ // which a class constructor inherits: TypeScript 5.9+ reports TS4114 without it
92
+ // under `noImplicitOverride`. Measured to compile on 5.5.4, 5.9.3, 6.0.3 and
93
+ // 7.0.2 with the flag on AND off — pinned by
94
+ // tests/custom-fetch-compiles-standalone.test.cjs.
95
+ static [Symbol.hasInstance](candidate) {
96
+ return (typeof candidate === 'object' &&
97
+ candidate !== null &&
98
+ CLIENT_ERROR_BRAND in candidate);
32
99
  }
33
100
  }
34
101
  exports.ClientError = ClientError;
35
102
  let clientConfig = null;
103
+ /**
104
+ * THE MOUNT SCOPE — how one process can host several services without their
105
+ * clients speaking for each other.
106
+ *
107
+ * `clientConfig` below is a MODULE global, and in a single-service process
108
+ * that is correct: one writer, one configuration. Compose two services into one
109
+ * process and both call `configureClient` on THIS SAME module instance, so the
110
+ * second overwrites the first and every outbound call from BOTH services leaves
111
+ * as whichever wired itself last — wrong base URL, and, because
112
+ * `getAuthToken` is part of the config, WRONG BEARER. That is one tenant's
113
+ * service calling a peer holding another tenant's credential, and it is silent.
114
+ *
115
+ * A composing host installs a hook under this well-known symbol that answers
116
+ * one question: WHICH MOUNT is currently on the stack. Nothing else crosses.
117
+ * `configureClient` then files the config under that mount, and
118
+ * `getClientConfig` reads it back out under the same key.
119
+ *
120
+ * Three properties make this safe rather than clever:
121
+ *
122
+ * - The CONFIG is still built by the mount's own wiring, exactly as today.
123
+ * The hook never supplies one. So a mount's base URL and bearer are
124
+ * resolved FROM THE MOUNT; the scope only decides which drawer they go in.
125
+ * A hook that RETURNED configuration would be a mount taking its identity
126
+ * from ambient storage a neighbour can write — the inversion to refuse.
127
+ * - The key is an OPAQUE OBJECT and the store is a `WeakMap`, so a mount's
128
+ * configuration becomes unreachable when the host drops the mount, and no
129
+ * client can enumerate the mounts or reach a sibling's entry.
130
+ * - With NO hook installed — every process in the fleet today — both
131
+ * functions behave exactly as they did before this existed.
132
+ *
133
+ * `Symbol.for` is the seam because a generated client must keep its
134
+ * dependency surface at zero and a host cannot enumerate the clients a process
135
+ * happens to load. It is the same instrument, and the same reasoning, as the
136
+ * `ClientError` brand above.
137
+ */
138
+ const XEMA_CLIENT_CONFIG_SCOPE = Symbol.for('xema.client-config-scope');
139
+ function mountScopeHook() {
140
+ const hook = globalThis[XEMA_CLIENT_CONFIG_SCOPE];
141
+ return typeof hook === 'function' ? hook : undefined;
142
+ }
143
+ function currentMountKey() {
144
+ return mountScopeHook()?.();
145
+ }
146
+ const perMountConfig = new WeakMap();
36
147
  function configureClient(config) {
37
148
  // Fail at WIRING time, not on the request that happens to be retried. A
38
149
  // client configured to retry without an observer is the exact defect this
@@ -42,9 +153,38 @@ function configureClient(config) {
42
153
  'reports is indistinguishable from a slow server, which is how two ' +
43
154
  'silent re-attempts were read as a 3,312ms call.');
44
155
  }
156
+ const hook = mountScopeHook();
157
+ if (hook !== undefined) {
158
+ const mount = hook();
159
+ if (mount === undefined) {
160
+ // A composing host is installed and no member is on the stack, so this
161
+ // configuration belongs to NO member. Filing it in the module global
162
+ // would hand it to every member that did not configure this client —
163
+ // someone else's base URL and bearer, silently.
164
+ throw new Error('configureClient: called in a composed process outside every member. ' +
165
+ 'Configure the client inside the member that uses it (its providers ' +
166
+ 'and factories already run there).');
167
+ }
168
+ perMountConfig.set(mount, config);
169
+ return;
170
+ }
45
171
  clientConfig = config;
46
172
  }
47
173
  function getClientConfig() {
174
+ const mount = currentMountKey();
175
+ if (mount !== undefined) {
176
+ const scoped = perMountConfig.get(mount);
177
+ if (scoped) {
178
+ return scoped;
179
+ }
180
+ // A member that never configured THIS client behaves exactly like a
181
+ // dedicated service that did not either: it is refused. It used to fall
182
+ // through to the module global, which in a composed process can only have
183
+ // been written by some OTHER code — so the member called peers under a
184
+ // base URL and bearer that were never its own.
185
+ throw new Error('Client not configured for this member. Call configureClient({ baseUrl }) ' +
186
+ 'inside the member before using endpoint functions.');
187
+ }
48
188
  if (!clientConfig) {
49
189
  throw new Error('Client not configured. Call configureClient({ baseUrl }) before using endpoint functions.');
50
190
  }
@@ -103,11 +243,64 @@ const CORRELATION_ID_HEADER = 'X-Correlation-Id';
103
243
  const BASE_BACKOFF_MS = 1000;
104
244
  /** Ceiling on a single backoff, however many attempts have elapsed. */
105
245
  const MAX_BACKOFF_MS = 30_000;
106
- async function buildHeaders(config, callerHeaders) {
246
+ /*
247
+ * CALLER CANCELLATION REACHES EVERY WAIT BEFORE THE REQUEST IS SENT.
248
+ *
249
+ * `fetch` always honoured `options.signal`, but everything this transport
250
+ * awaits BEFORE `fetch` — base-URL resolution, the header callbacks, the auth
251
+ * token — did not, so a caller that aborted while a token was being minted sat
252
+ * out the mint and then, at best, had its request refused. The only way to
253
+ * cancel that wait was a process-wide interceptor aborting every outbound
254
+ * request, which also aborts a SHARED single-flight token refresh and so fails
255
+ * every other caller waiting on it.
256
+ *
257
+ * So each pre-send wait is RACED against the signal: the caller stops waiting
258
+ * at once, and the work it was waiting on carries on for anybody else. The
259
+ * rejection is the signal's own reason — exactly what `fetch` rejects with —
260
+ * so a caller sees ONE abort shape whenever it aborts. An aborted request is
261
+ * never retried. Without a signal nothing here changes.
262
+ */
263
+ function abortedReason(signal) {
264
+ // `abort()` with no argument sets a DOMException reason, so this is only
265
+ // ever `undefined` for a hand-built signal; say so rather than throw it.
266
+ return signal.reason ?? new DOMException('This operation was aborted', 'AbortError');
267
+ }
268
+ function throwIfAborted(signal) {
269
+ if (signal?.aborted) {
270
+ throw abortedReason(signal);
271
+ }
272
+ }
273
+ function raceAbort(pending, signal) {
274
+ const promise = Promise.resolve(pending);
275
+ if (!signal) {
276
+ return promise;
277
+ }
278
+ if (signal.aborted) {
279
+ promise.catch(() => undefined);
280
+ return Promise.reject(abortedReason(signal));
281
+ }
282
+ return new Promise((resolve, reject) => {
283
+ const onAbort = () => {
284
+ // The pending work may be shared; it carries on, and its eventual
285
+ // rejection must not surface as an unhandled one on this side.
286
+ promise.catch(() => undefined);
287
+ reject(abortedReason(signal));
288
+ };
289
+ signal.addEventListener('abort', onAbort, { once: true });
290
+ promise.then((value) => {
291
+ signal.removeEventListener('abort', onAbort);
292
+ resolve(value);
293
+ }, (err) => {
294
+ signal.removeEventListener('abort', onAbort);
295
+ reject(err);
296
+ });
297
+ });
298
+ }
299
+ async function buildHeaders(config, callerHeaders, signal) {
107
300
  const headers = new Headers(callerHeaders);
108
301
  // Global headers from config (caller-provided headers take precedence)
109
302
  if (config.getHeaders) {
110
- const globalHeaders = await Promise.resolve(config.getHeaders());
303
+ const globalHeaders = await raceAbort(config.getHeaders(), signal);
111
304
  for (const [key, value] of Object.entries(globalHeaders)) {
112
305
  if (!headers.has(key)) {
113
306
  headers.set(key, value);
@@ -126,14 +319,14 @@ async function buildHeaders(config, callerHeaders) {
126
319
  // receiver mints and a new trace begins, which is the truthful outcome when
127
320
  // there is nothing to continue.
128
321
  if (config.getCorrelationId && !headers.has(CORRELATION_ID_HEADER)) {
129
- const correlationId = await Promise.resolve(config.getCorrelationId());
322
+ const correlationId = await raceAbort(config.getCorrelationId(), signal);
130
323
  if (correlationId) {
131
324
  headers.set(CORRELATION_ID_HEADER, correlationId);
132
325
  }
133
326
  }
134
327
  // Auth token (caller or global headers take precedence)
135
328
  if (config.getAuthToken && !headers.has('Authorization')) {
136
- const token = await config.getAuthToken();
329
+ const token = await raceAbort(config.getAuthToken(signal ? { signal } : undefined), signal);
137
330
  headers.set('Authorization', `Bearer ${token}`);
138
331
  }
139
332
  return headers;
@@ -163,8 +356,10 @@ async function buildHeaders(config, callerHeaders) {
163
356
  */
164
357
  const customFetch = async (url, options) => {
165
358
  const config = getClientConfig();
359
+ const signal = options.signal ?? undefined;
360
+ throwIfAborted(signal);
166
361
  const base = config.baseUrlResolver
167
- ? await config.baseUrlResolver()
362
+ ? await raceAbort(config.baseUrlResolver(signal ? { signal } : undefined), signal)
168
363
  : config.baseUrl;
169
364
  if (base === undefined) {
170
365
  throw new Error('Client not configured: set baseUrl or baseUrlResolver via configureClient().');
@@ -176,7 +371,7 @@ const customFetch = async (url, options) => {
176
371
  // re-sending would replay the identical failing request with the identical
177
372
  // credential: one wasted round trip, plus a global refresh nobody asked for.
178
373
  const callerSuppliedAuth = new Headers(options.headers).has('Authorization');
179
- const headers = await buildHeaders(config, options.headers);
374
+ const headers = await buildHeaders(config, options.headers, signal);
180
375
  const requestInit = { ...options, headers };
181
376
  let delay = BASE_BACKOFF_MS;
182
377
  for (let attempt = 0;; attempt++) {
@@ -185,8 +380,8 @@ const customFetch = async (url, options) => {
185
380
  config.onUnauthorized &&
186
381
  !callerSuppliedAuth &&
187
382
  attempt === 0) {
188
- await config.onUnauthorized();
189
- const refreshedHeaders = await buildHeaders(config, options.headers);
383
+ await raceAbort(config.onUnauthorized(), signal);
384
+ const refreshedHeaders = await buildHeaders(config, options.headers, signal);
190
385
  const retryResponse = await fetch(fullUrl, {
191
386
  ...options,
192
387
  headers: refreshedHeaders,
@@ -218,7 +413,7 @@ const customFetch = async (url, options) => {
218
413
  url: fullUrl,
219
414
  method: options.method ?? 'GET',
220
415
  });
221
- await sleep(waitMs);
416
+ await sleep(waitMs, signal);
222
417
  delay = Math.min(delay * 2, MAX_BACKOFF_MS);
223
418
  }
224
419
  };
@@ -299,7 +494,24 @@ function parseRetryAfter(value) {
299
494
  function addJitter(delay) {
300
495
  return delay + (Math.random() * 2 - 1) * delay * 0.25;
301
496
  }
302
- function sleep(ms) {
303
- return new Promise((resolve) => setTimeout(resolve, ms));
497
+ /** A retry backoff; the caller's signal ends it at once and is never retried. */
498
+ function sleep(ms, signal) {
499
+ if (!signal) {
500
+ return new Promise((resolve) => setTimeout(resolve, ms));
501
+ }
502
+ if (signal.aborted) {
503
+ return Promise.reject(abortedReason(signal));
504
+ }
505
+ return new Promise((resolve, reject) => {
506
+ const onAbort = () => {
507
+ clearTimeout(timer);
508
+ reject(abortedReason(signal));
509
+ };
510
+ const timer = setTimeout(() => {
511
+ signal.removeEventListener('abort', onAbort);
512
+ resolve();
513
+ }, ms);
514
+ signal.addEventListener('abort', onAbort, { once: true });
515
+ });
304
516
  }
305
517
  exports.default = exports.customFetch;
@@ -6,7 +6,7 @@
6
6
  import type { SubjectKind } from './subjectKind.js';
7
7
  export interface AssignRoleDto {
8
8
  /**
9
- * The org this assignment is scoped to. For a custom role it must equal the role’s org; for a built-in role (system sentinel) it is the real consuming org.
9
+ * The org this assignment is scoped to. For a custom role it must equal the role’s org; for a built-in (platform-owned) role it is the real consuming org.
10
10
  * @minLength 1
11
11
  */
12
12
  orgId: string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Generated by @xemahq/api-client-generator — do not edit manually.
3
+ * Authorization API
4
+ * OpenAPI spec version: 0.1.1
5
+ */
6
+ /**
7
+ * Who owns this grant: `system` (the platform — kernel-seeded, shared by every org) or `org`. The admissible subset of the kernel `SpaceKind` for a role or a capability grant.
8
+ */
9
+ export type AuthorityRowOwnerSpaceKind = typeof AuthorityRowOwnerSpaceKind[keyof typeof AuthorityRowOwnerSpaceKind];
10
+ export declare const AuthorityRowOwnerSpaceKind: {
11
+ readonly system: "system";
12
+ readonly org: "org";
13
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /**
3
+ * Generated by @xemahq/api-client-generator — do not edit manually.
4
+ * Authorization API
5
+ * OpenAPI spec version: 0.1.1
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.AuthorityRowOwnerSpaceKind = void 0;
9
+ exports.AuthorityRowOwnerSpaceKind = {
10
+ system: 'system',
11
+ org: 'org',
12
+ };
@@ -3,13 +3,19 @@
3
3
  * Authorization API
4
4
  * OpenAPI spec version: 0.1.1
5
5
  */
6
+ import type { AuthorityRowOwnerSpaceKind } from './authorityRowOwnerSpaceKind.js';
6
7
  import type { BiomePermissionProfile } from './biomePermissionProfile.js';
7
8
  import type { GrantConstraintsDto } from './grantConstraintsDto.js';
8
9
  import type { SubjectKind } from './subjectKind.js';
9
10
  export interface CapabilityGrantDto {
10
11
  id: string;
11
- /** Organization identifier this grant is scoped to. */
12
- orgId: string;
12
+ /**
13
+ * The owning organisation, or null when the PLATFORM owns this grant (`ownerSpaceKind` = system).
14
+ * @nullable
15
+ */
16
+ orgId: string | null;
17
+ /** Who owns this grant: `system` (the platform — kernel-seeded, shared by every org) or `org`. The admissible subset of the kernel `SpaceKind` for a role or a capability grant. */
18
+ ownerSpaceKind: AuthorityRowOwnerSpaceKind;
13
19
  subjectKind: SubjectKind;
14
20
  subjectRef: string;
15
21
  capability: string;
@@ -5,6 +5,7 @@ export * from './agentProvisionDecision';
5
5
  export * from './agentProvisionReason';
6
6
  export * from './agentReachTier';
7
7
  export * from './assignRoleDto';
8
+ export * from './authorityRowOwnerSpaceKind';
8
9
  export * from './authorizationCheckRequestDto';
9
10
  export * from './authorizationCheckResponseDto';
10
11
  export * from './authorizationCheckResponseDtoDataEnvelope';
@@ -121,6 +122,7 @@ export * from './policyConstraintsDto';
121
122
  export * from './policyDecisionDto';
122
123
  export * from './policyDecisionDtoDataEnvelope';
123
124
  export * from './policyDecisionKind';
125
+ export * from './policyDelegatedAuthorityDto';
124
126
  export * from './policyEnvironmentDto';
125
127
  export * from './policyObligationDto';
126
128
  export * from './policyObligationKind';
@@ -22,6 +22,7 @@ __exportStar(require("./agentProvisionDecision"), exports);
22
22
  __exportStar(require("./agentProvisionReason"), exports);
23
23
  __exportStar(require("./agentReachTier"), exports);
24
24
  __exportStar(require("./assignRoleDto"), exports);
25
+ __exportStar(require("./authorityRowOwnerSpaceKind"), exports);
25
26
  __exportStar(require("./authorizationCheckRequestDto"), exports);
26
27
  __exportStar(require("./authorizationCheckResponseDto"), exports);
27
28
  __exportStar(require("./authorizationCheckResponseDtoDataEnvelope"), exports);
@@ -138,6 +139,7 @@ __exportStar(require("./policyConstraintsDto"), exports);
138
139
  __exportStar(require("./policyDecisionDto"), exports);
139
140
  __exportStar(require("./policyDecisionDtoDataEnvelope"), exports);
140
141
  __exportStar(require("./policyDecisionKind"), exports);
142
+ __exportStar(require("./policyDelegatedAuthorityDto"), exports);
141
143
  __exportStar(require("./policyEnvironmentDto"), exports);
142
144
  __exportStar(require("./policyObligationDto"), exports);
143
145
  __exportStar(require("./policyObligationKind"), exports);
@@ -18,4 +18,5 @@ export declare const OpenCapabilityAuthorityRequestDtoSubjectKind: {
18
18
  readonly runner: "runner";
19
19
  readonly 'external-subject': "external-subject";
20
20
  readonly anon: "anon";
21
+ readonly organization: "organization";
21
22
  };
@@ -17,4 +17,5 @@ exports.OpenCapabilityAuthorityRequestDtoSubjectKind = {
17
17
  runner: 'runner',
18
18
  'external-subject': 'external-subject',
19
19
  anon: 'anon',
20
+ organization: 'organization',
20
21
  };
@@ -10,6 +10,7 @@ import type { PolicyCallerDto } from './policyCallerDto.js';
10
10
  import type { PolicyCapabilityDto } from './policyCapabilityDto.js';
11
11
  import type { PolicyCheckRequestDtoAperture } from './policyCheckRequestDtoAperture.js';
12
12
  import type { PolicyConstraintsDto } from './policyConstraintsDto.js';
13
+ import type { PolicyDelegatedAuthorityDto } from './policyDelegatedAuthorityDto.js';
13
14
  import type { PolicyEnvironmentDto } from './policyEnvironmentDto.js';
14
15
  import type { PolicyResourceDto } from './policyResourceDto.js';
15
16
  import type { PolicySpaceRefDto } from './policySpaceRefDto.js';
@@ -31,6 +32,13 @@ export interface PolicyCheckRequestDto {
31
32
  resource?: PolicyResourceDto;
32
33
  constraints?: PolicyConstraintsDto;
33
34
  actorChain?: PolicyActingForDto[];
35
+ /**
36
+ * The caller's VERIFIED delegated authority (kernel
37
+ * `ExecutionContext.delegation`). A CEILING, never a grant — see
38
+ * {@link PolicyDelegatedAuthorityDto} and the PDP stage that reads it
39
+ * (`AuthorizationService.applyDelegatedAuthorityCeiling`).
40
+ */
41
+ delegation?: PolicyDelegatedAuthorityDto;
34
42
  /**
35
43
  * Opaque credential-binding id already selected for this invocation. Carried
36
44
  * on the kernel envelope (a re-checked / replayed context round-trips it), so
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Generated by @xemahq/api-client-generator — do not edit manually.
3
+ * Authorization API
4
+ * OpenAPI spec version: 0.1.1
5
+ */
6
+ import type { PolicyActingForDto } from './policyActingForDto.js';
7
+ export interface PolicyDelegatedAuthorityDto {
8
+ /** @minLength 1 */
9
+ delegationId: string;
10
+ actor: PolicyActingForDto;
11
+ /** @minItems 1 */
12
+ actorChain: PolicyActingForDto[];
13
+ /**
14
+ * @minItems 1
15
+ * @items.minLength 1
16
+ */
17
+ capabilities: string[];
18
+ /**
19
+ * @minItems 1
20
+ * @items.minLength 1
21
+ */
22
+ resourceScope?: string[];
23
+ /** @minLength 1 */
24
+ authorizedBy?: string;
25
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -3,10 +3,17 @@
3
3
  * Authorization API
4
4
  * OpenAPI spec version: 0.1.1
5
5
  */
6
+ import type { AuthorityRowOwnerSpaceKind } from './authorityRowOwnerSpaceKind.js';
6
7
  import type { ResourceManagedBy } from './resourceManagedBy.js';
7
8
  export interface RoleDto {
8
9
  id: string;
9
- orgId: string;
10
+ /**
11
+ * The owning organisation, or null when the PLATFORM owns this role (`ownerSpaceKind` = system).
12
+ * @nullable
13
+ */
14
+ orgId: string | null;
15
+ /** Who owns this role: `system` (the platform — kernel-seeded, shared by every org) or `org`. The admissible subset of the kernel `SpaceKind` for a role or a capability grant. */
16
+ ownerSpaceKind: AuthorityRowOwnerSpaceKind;
10
17
  slug: string;
11
18
  displayName: string;
12
19
  /** @nullable */
@@ -15,4 +15,5 @@ export declare const SubjectKind: {
15
15
  readonly runner: "runner";
16
16
  readonly 'external-subject': "external-subject";
17
17
  readonly anon: "anon";
18
+ readonly organization: "organization";
18
19
  };
@@ -17,4 +17,5 @@ exports.SubjectKind = {
17
17
  runner: 'runner',
18
18
  'external-subject': 'external-subject',
19
19
  anon: 'anon',
20
+ organization: 'organization',
20
21
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/authorization-internal-api-client",
3
- "version": "0.4.28",
3
+ "version": "0.5.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -19,7 +19,7 @@
19
19
  "service": "authorization-api",
20
20
  "biome": "authorization",
21
21
  "target": "server",
22
- "generator": "@xemahq/api-client-generator@0.21.0",
22
+ "generator": "@xemahq/api-client-generator@2.1.1",
23
23
  "source": "openapi.internal.json"
24
24
  },
25
25
  "license": "LicenseRef-Xema-BSL-1.1",