@uluops/ops-sdk 6.1.0 → 6.4.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.
- package/CHANGELOG.md +93 -1
- package/README.md +231 -2
- package/dist/client.d.ts +155 -81
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +141 -67
- package/dist/client.js.map +1 -1
- package/dist/config/constants.d.ts +3 -1
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +2 -0
- package/dist/config/constants.js.map +1 -1
- package/dist/config/generated-version.d.ts +1 -1
- package/dist/config/generated-version.js +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/validators.d.ts +25 -1
- package/dist/config/validators.d.ts.map +1 -1
- package/dist/config/validators.js +31 -1
- package/dist/config/validators.js.map +1 -1
- package/dist/config/workspace-org.d.ts +77 -0
- package/dist/config/workspace-org.d.ts.map +1 -0
- package/dist/config/workspace-org.js +182 -0
- package/dist/config/workspace-org.js.map +1 -0
- package/dist/errors/errors.d.ts +118 -0
- package/dist/errors/errors.d.ts.map +1 -1
- package/dist/errors/errors.js +138 -0
- package/dist/errors/errors.js.map +1 -1
- package/dist/http/http-client.d.ts +46 -0
- package/dist/http/http-client.d.ts.map +1 -1
- package/dist/http/http-client.js +88 -5
- package/dist/http/http-client.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/operations/admin.d.ts +100 -0
- package/dist/operations/admin.d.ts.map +1 -0
- package/dist/operations/admin.js +130 -0
- package/dist/operations/admin.js.map +1 -0
- package/dist/operations/auth.d.ts +21 -1
- package/dist/operations/auth.d.ts.map +1 -1
- package/dist/operations/auth.js +49 -3
- package/dist/operations/auth.js.map +1 -1
- package/dist/operations/orgs.d.ts +27 -0
- package/dist/operations/orgs.d.ts.map +1 -0
- package/dist/operations/orgs.js +34 -0
- package/dist/operations/orgs.js.map +1 -0
- package/dist/operations/projects.d.ts +46 -0
- package/dist/operations/projects.d.ts.map +1 -1
- package/dist/operations/projects.js +54 -1
- package/dist/operations/projects.js.map +1 -1
- package/dist/types/auth.d.ts +10 -0
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/org.d.ts +25 -0
- package/dist/types/org.d.ts.map +1 -0
- package/dist/types/org.js +2 -0
- package/dist/types/org.js.map +1 -0
- package/dist/types/rehome.d.ts +234 -0
- package/dist/types/rehome.d.ts.map +1 -0
- package/dist/types/rehome.js +171 -0
- package/dist/types/rehome.js.map +1 -0
- package/dist/types/response-schemas.d.ts +19 -0
- package/dist/types/response-schemas.d.ts.map +1 -1
- package/dist/types/response-schemas.js +19 -0
- package/dist/types/response-schemas.js.map +1 -1
- package/dist/types/schemas.d.ts +20 -0
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/schemas.js +22 -0
- package/dist/types/schemas.js.map +1 -1
- package/package.json +1 -1
|
@@ -68,6 +68,10 @@ export interface HttpClientConfig {
|
|
|
68
68
|
/** Org slug for multi-tenancy — sets X-Org-Slug header on all requests */
|
|
69
69
|
orgSlug?: string;
|
|
70
70
|
}
|
|
71
|
+
/** Alphanumeric + hyphens/underscores, 1–100 chars */
|
|
72
|
+
export declare const ORG_SLUG_PATTERN: RegExp;
|
|
73
|
+
/** The header the tracker's org-context middleware reads (after `:slug` and `X-Org-Id`). */
|
|
74
|
+
export declare const ORG_SLUG_HEADER = "X-Org-Slug";
|
|
71
75
|
/**
|
|
72
76
|
* HTTP client for ops-uluops-api using native fetch
|
|
73
77
|
*/
|
|
@@ -82,6 +86,48 @@ export declare class OpsHttpClient extends HttpClient {
|
|
|
82
86
|
* @throws {InputValidationError} If `orgSlug` is present but not 1–100
|
|
83
87
|
* alphanumeric characters, hyphens, or underscores.
|
|
84
88
|
*/
|
|
89
|
+
/**
|
|
90
|
+
* Per-call org override (project-org-routing-and-rehome spec §3.2, 6.2.0).
|
|
91
|
+
* Set only on views minted by {@link withOrg}; the root client never has one.
|
|
92
|
+
*/
|
|
93
|
+
private orgOverride?;
|
|
94
|
+
/**
|
|
95
|
+
* Set instead of throwing when `withOrg` is handed an invalid slug: every
|
|
96
|
+
* method on OpsClient returns a Promise, so the caller's `.catch`/`await`
|
|
97
|
+
* must see the error — a synchronous throw from inside a non-async arrow
|
|
98
|
+
* would escape both. Surfaced as a rejection of the view's first request.
|
|
99
|
+
*/
|
|
100
|
+
private orgInvalid?;
|
|
85
101
|
constructor(config?: HttpClientConfig);
|
|
102
|
+
/**
|
|
103
|
+
* A view of this client whose every request carries `X-Org-Slug: <org>`,
|
|
104
|
+
* overriding the constructor-level `orgSlug` (per-request headers win over
|
|
105
|
+
* `defaultHeaders` in sdk-core). The view shares this client's auth
|
|
106
|
+
* strategy, fetch adapter and configuration — it is the same client, seen
|
|
107
|
+
* through one org — so a session installed on the root is honoured here.
|
|
108
|
+
*
|
|
109
|
+
* Precedence on the wire, lowest to highest: personal org (no header) <
|
|
110
|
+
* constructor `orgSlug` < this per-call `org`. An API key BOUND to an org
|
|
111
|
+
* ignores both headers and 403s (`ORG_ACCESS_DENIED`) if they name a
|
|
112
|
+
* different org — that is the platform's rule, surfaced verbatim.
|
|
113
|
+
*
|
|
114
|
+
* An invalid `org` (not 1–100 alphanumeric characters, hyphens, or
|
|
115
|
+
* underscores — the same pattern as `orgSlug`; it is a header value, so
|
|
116
|
+
* CRLF/whitespace can never reach the wire) does not throw here: the view's
|
|
117
|
+
* requests REJECT with `InputValidationError` before anything is sent, so
|
|
118
|
+
* `await client.projects.list({ org })` fails the way every other input
|
|
119
|
+
* error does.
|
|
120
|
+
*/
|
|
121
|
+
withOrg(org: string): OpsHttpClient;
|
|
122
|
+
/** The org this view is scoped to, or `undefined` on the root client. */
|
|
123
|
+
get scopedOrg(): string | undefined;
|
|
124
|
+
request<T>(method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE', endpoint: string, data?: object, options?: {
|
|
125
|
+
params?: object;
|
|
126
|
+
retries?: number;
|
|
127
|
+
retryMutations?: boolean;
|
|
128
|
+
headers?: Record<string, string>;
|
|
129
|
+
skipAuth?: boolean;
|
|
130
|
+
rawEnvelope?: boolean;
|
|
131
|
+
}): Promise<T>;
|
|
86
132
|
}
|
|
87
133
|
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/http/http-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAKlE,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAKzF,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,QAAQ,EACR,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,KAAK,WAAW,IAAI,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAGjE;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,CAiBrE;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,4EAA4E;IAC5E,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,kBAAkB,EAAE,aAAa,KAAK,IAAI,CAAC;IAClF,oFAAoF;IACpF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClG;;;;OAIG;IACH,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/http/http-client.ts"],"names":[],"mappings":"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"}
|
package/dist/http/http-client.js
CHANGED
|
@@ -47,7 +47,14 @@ export function toApiQuery(query) {
|
|
|
47
47
|
return Object.keys(params).length > 0 ? params : undefined;
|
|
48
48
|
}
|
|
49
49
|
/** Alphanumeric + hyphens/underscores, 1–100 chars */
|
|
50
|
-
const ORG_SLUG_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,99}$/;
|
|
50
|
+
export const ORG_SLUG_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,99}$/;
|
|
51
|
+
/** The header the tracker's org-context middleware reads (after `:slug` and `X-Org-Id`). */
|
|
52
|
+
export const ORG_SLUG_HEADER = 'X-Org-Slug';
|
|
53
|
+
function assertOrgSlug(value, path) {
|
|
54
|
+
if (!ORG_SLUG_PATTERN.test(value)) {
|
|
55
|
+
throw new InputValidationError(`Invalid ${path}: must be 1-100 alphanumeric characters, hyphens, or underscores`, [{ code: 'custom', path: [path], message: 'must be 1-100 alphanumeric characters, hyphens, or underscores' }]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
51
58
|
/**
|
|
52
59
|
* HTTP client for ops-uluops-api using native fetch
|
|
53
60
|
*/
|
|
@@ -62,10 +69,21 @@ export class OpsHttpClient extends HttpClient {
|
|
|
62
69
|
* @throws {InputValidationError} If `orgSlug` is present but not 1–100
|
|
63
70
|
* alphanumeric characters, hyphens, or underscores.
|
|
64
71
|
*/
|
|
72
|
+
/**
|
|
73
|
+
* Per-call org override (project-org-routing-and-rehome spec §3.2, 6.2.0).
|
|
74
|
+
* Set only on views minted by {@link withOrg}; the root client never has one.
|
|
75
|
+
*/
|
|
76
|
+
orgOverride;
|
|
77
|
+
/**
|
|
78
|
+
* Set instead of throwing when `withOrg` is handed an invalid slug: every
|
|
79
|
+
* method on OpsClient returns a Promise, so the caller's `.catch`/`await`
|
|
80
|
+
* must see the error — a synchronous throw from inside a non-async arrow
|
|
81
|
+
* would escape both. Surfaced as a rejection of the view's first request.
|
|
82
|
+
*/
|
|
83
|
+
orgInvalid;
|
|
65
84
|
constructor(config = {}) {
|
|
66
|
-
if (config.orgSlug
|
|
67
|
-
|
|
68
|
-
}
|
|
85
|
+
if (config.orgSlug)
|
|
86
|
+
assertOrgSlug(config.orgSlug, 'orgSlug');
|
|
69
87
|
super({
|
|
70
88
|
...config,
|
|
71
89
|
baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
|
|
@@ -73,9 +91,74 @@ export class OpsHttpClient extends HttpClient {
|
|
|
73
91
|
sdkVersion: SDK_VERSION,
|
|
74
92
|
loggerPrefix: '[ops-sdk:http]',
|
|
75
93
|
defaultHeaders: {
|
|
76
|
-
...(config.orgSlug ? {
|
|
94
|
+
...(config.orgSlug ? { [ORG_SLUG_HEADER]: config.orgSlug } : {}),
|
|
77
95
|
},
|
|
78
96
|
});
|
|
79
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* A view of this client whose every request carries `X-Org-Slug: <org>`,
|
|
100
|
+
* overriding the constructor-level `orgSlug` (per-request headers win over
|
|
101
|
+
* `defaultHeaders` in sdk-core). The view shares this client's auth
|
|
102
|
+
* strategy, fetch adapter and configuration — it is the same client, seen
|
|
103
|
+
* through one org — so a session installed on the root is honoured here.
|
|
104
|
+
*
|
|
105
|
+
* Precedence on the wire, lowest to highest: personal org (no header) <
|
|
106
|
+
* constructor `orgSlug` < this per-call `org`. An API key BOUND to an org
|
|
107
|
+
* ignores both headers and 403s (`ORG_ACCESS_DENIED`) if they name a
|
|
108
|
+
* different org — that is the platform's rule, surfaced verbatim.
|
|
109
|
+
*
|
|
110
|
+
* An invalid `org` (not 1–100 alphanumeric characters, hyphens, or
|
|
111
|
+
* underscores — the same pattern as `orgSlug`; it is a header value, so
|
|
112
|
+
* CRLF/whitespace can never reach the wire) does not throw here: the view's
|
|
113
|
+
* requests REJECT with `InputValidationError` before anything is sent, so
|
|
114
|
+
* `await client.projects.list({ org })` fails the way every other input
|
|
115
|
+
* error does.
|
|
116
|
+
*/
|
|
117
|
+
withOrg(org) {
|
|
118
|
+
// `"personal"` is the reserved no-org value (the same sentinel the
|
|
119
|
+
// workspace file uses): the root client, no per-call header. It does not
|
|
120
|
+
// cancel a constructor-level `orgSlug` — that is a defaultHeader sdk-core
|
|
121
|
+
// always sends; callers that need "personal despite a constructor org"
|
|
122
|
+
// construct without one (the tracker MCP has none since 2.1.0).
|
|
123
|
+
if (org === 'personal')
|
|
124
|
+
return this;
|
|
125
|
+
// Prototype-chained view: reads (auth strategy, adapter, config) fall
|
|
126
|
+
// through to this instance; only the override fields are set on the view.
|
|
127
|
+
// sdk-core's verbs (get/post/patch/put/delete) all delegate to `request`,
|
|
128
|
+
// so the override below covers every operation without touching them.
|
|
129
|
+
const view = Object.create(this);
|
|
130
|
+
try {
|
|
131
|
+
assertOrgSlug(org, 'org');
|
|
132
|
+
view.orgOverride = org;
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
view.orgInvalid = err;
|
|
136
|
+
}
|
|
137
|
+
return view;
|
|
138
|
+
}
|
|
139
|
+
/** The org this view is scoped to, or `undefined` on the root client. */
|
|
140
|
+
get scopedOrg() {
|
|
141
|
+
return this.orgOverride;
|
|
142
|
+
}
|
|
143
|
+
request(method, endpoint, data, options) {
|
|
144
|
+
if (this.orgInvalid)
|
|
145
|
+
return Promise.reject(this.orgInvalid);
|
|
146
|
+
if (this.orgOverride === undefined)
|
|
147
|
+
return super.request(method, endpoint, data, options);
|
|
148
|
+
// The per-call org is set LAST so a caller-supplied header cannot outrank
|
|
149
|
+
// it, and an org header in `options.headers` is refused outright: until
|
|
150
|
+
// 6.3.1 the spread order let `options.headers` win, and `X-Org-Id`
|
|
151
|
+
// outranks `X-Org-Slug` on the server, so a smuggled header would have
|
|
152
|
+
// silently redirected a scoped call (run #187, circumvention A7 /
|
|
153
|
+
// trust-boundary F7 — no live caller did this; the invariant held by luck).
|
|
154
|
+
const smuggled = Object.keys(options?.headers ?? {}).find((h) => /^x-org-(slug|id)$/i.test(h));
|
|
155
|
+
if (smuggled !== undefined) {
|
|
156
|
+
return Promise.reject(new InputValidationError(`Refusing request header ${smuggled} on an org-scoped call: the per-call org (${this.orgOverride}) is the only org channel`, [{ code: 'custom', path: ['headers', smuggled], message: 'org headers may not be set per request on a scoped view' }]));
|
|
157
|
+
}
|
|
158
|
+
return super.request(method, endpoint, data, {
|
|
159
|
+
...options,
|
|
160
|
+
headers: { ...(options?.headers ?? {}), [ORG_SLUG_HEADER]: this.orgOverride },
|
|
161
|
+
});
|
|
162
|
+
}
|
|
80
163
|
}
|
|
81
164
|
//# sourceMappingURL=http-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/http/http-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,2EAA2E;AAC3E,OAAO,EAAE,OAAO,EAA0C,MAAM,wBAAwB,CAAC;AAiBzF,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,KAAyB;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC3G,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QACnC,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,qEAAqE;YACrE,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;YACrF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QACD,mEAAmE;IACrE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAyCD,sDAAsD;AACtD,MAAM,gBAAgB,GAAG,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/http/http-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Types: All domain interfaces (Run, Issue, AgentInput, SaveRunInput, etc.)
|
|
8
8
|
* - Config: Credential loading and environment variable helpers
|
|
9
9
|
*/
|
|
10
|
-
export { OpsClient, type OpsClientConfig } from './client.js';
|
|
10
|
+
export { OpsClient, type OpsClientConfig, type LoginOptions } from './client.js';
|
|
11
11
|
export { OpsHttpClient, type HttpClientConfig, type QueryParams, type QueryParamValue } from './http/http-client.js';
|
|
12
12
|
export type { SecurityEvent, SecurityEventType, SecurityEventHandler, AuthType, AuthFailureEvent, RedirectRejectedEvent, TokenRefreshFailedEvent, AuthStrategyReplacedEvent, } from './http/http-client.js';
|
|
13
13
|
export { ApiKeyAuth, JwtSessionAuth, createAuthStrategy, type AuthStrategy, type AuthConfig } from './http/auth-strategy.js';
|
|
@@ -16,4 +16,5 @@ export * from './types/index.js';
|
|
|
16
16
|
export { isValidMetric, ANALYTICS_METRICS, type AnalyticsMetric } from './operations/analytics.js';
|
|
17
17
|
export { loadCredentials, loadConfig, loadEnvFiles, type Credentials, type SdkConfig } from './config/loaders.js';
|
|
18
18
|
export { DEFAULT_BASE_URL, API_KEY_PREFIX, ENV_VARS } from './config/constants.js';
|
|
19
|
+
export { resolveWorkspaceOrg, findWorkspaceOrgFile, readWorkspaceOrgFile, WORKSPACE_ORG_FILE, PERSONAL_ORG_SENTINEL, type WorkspaceOrgResolution, type WorkspaceOrgSource, type ResolveWorkspaceOrgOptions, } from './config/workspace-org.js';
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAGjF,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACrH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,QAAQ,EACR,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG7H,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGnG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,GAChC,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -21,4 +21,5 @@ export { isValidMetric, ANALYTICS_METRICS } from './operations/analytics.js';
|
|
|
21
21
|
// Config — credential loading from env vars, .env files, and ~/.uluops/credentials.json
|
|
22
22
|
export { loadCredentials, loadConfig, loadEnvFiles } from './config/loaders.js';
|
|
23
23
|
export { DEFAULT_BASE_URL, API_KEY_PREFIX, ENV_VARS } from './config/constants.js';
|
|
24
|
+
export { resolveWorkspaceOrg, findWorkspaceOrgFile, readWorkspaceOrgFile, WORKSPACE_ORG_FILE, PERSONAL_ORG_SENTINEL, } from './config/workspace-org.js';
|
|
24
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,2DAA2D;AAC3D,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,2DAA2D;AAC3D,OAAO,EAAE,SAAS,EAA2C,MAAM,aAAa,CAAC;AAEjF,oFAAoF;AACpF,OAAO,EAAE,aAAa,EAAiE,MAAM,uBAAuB,CAAC;AAWrH,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAsC,MAAM,yBAAyB,CAAC;AAE7H,0EAA0E;AAC1E,cAAc,oBAAoB,CAAC;AAEnC,gEAAgE;AAChE,cAAc,kBAAkB,CAAC;AAEjC,mEAAmE;AACnE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAwB,MAAM,2BAA2B,CAAC;AAEnG,wFAAwF;AACxF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAoC,MAAM,qBAAqB,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,GAItB,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { OpsHttpClient } from '../http/http-client.js';
|
|
2
|
+
import type { AdminRehomeProjectInput, RehomeResponse, ProjectRehomeList, ProjectRehomeListQuery, ProjectRehomeEventList, ProjectRehomeEventListQuery } from '../types/rehome.js';
|
|
3
|
+
/**
|
|
4
|
+
* Platform-admin project re-home surface (project-org-routing-and-rehome spec
|
|
5
|
+
* §4.1 D8, §4.7, D20, D21). Every call here requires `users.role = 'admin'` —
|
|
6
|
+
* a PLATFORM role, not an org role — and the two writes additionally require
|
|
7
|
+
* a login-issued SESSION (D20): a `ulr_` key, even an admin's, gets
|
|
8
|
+
* `403 SESSION_REQUIRED` (`isSessionRequiredError`). Log in with
|
|
9
|
+
* `OpsClient.login` (completing MFA via `loginWithTotp` if challenged) and the
|
|
10
|
+
* session bearer is what these calls send. There is deliberately no MCP tool
|
|
11
|
+
* for any of this.
|
|
12
|
+
*
|
|
13
|
+
* `admin.` is a namespace, not an escalation: the same client, the same auth
|
|
14
|
+
* strategy. If the credential cannot do it the server says so.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Move ANY project between ANY two orgs — `POST /admin/projects/:id/rehome`.
|
|
18
|
+
* No source-membership and no target-membership requirement (the platform role
|
|
19
|
+
* is the authority), so `reason` is REQUIRED: on this path the target org's
|
|
20
|
+
* only standing is the `rehome_in` audit row plus that text. Resolves the
|
|
21
|
+
* project by id UNSCOPED (the admin router has no org context) — the route
|
|
22
|
+
* takes a UUID and answers 400 to anything else, so unlike `projects.*` a
|
|
23
|
+
* NAME is refused here, client-side, before the request.
|
|
24
|
+
*
|
|
25
|
+
* Session-only (D20). Phase 4 of the spec runs this once per row of the OQ-4
|
|
26
|
+
* table, sequentially, with the row reference as `reason`. On THIS path a
|
|
27
|
+
* re-run over a finished row answers `same_org` (the lookup is by id, so the
|
|
28
|
+
* moved project is found wherever it is) — read it as "already done" via
|
|
29
|
+
* `rehomeRefusalReason`. That is not true of the member path, whose lookup is
|
|
30
|
+
* source-scoped (see `projects.rehome`).
|
|
31
|
+
*
|
|
32
|
+
* @param client - HTTP client instance carrying a SESSION
|
|
33
|
+
* @param projectId - Project UUID (a name is an `InputValidationError`)
|
|
34
|
+
* @param input - `{ targetOrg, reason }` — both required
|
|
35
|
+
* @returns The project after the move (`orgId` is the target) plus the `rehome` block
|
|
36
|
+
* @throws {InputValidationError} If `projectId` is not a UUID, `targetOrg` is not a slug, or `reason` is missing
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* await client.login(email, password); // or loginWithTotp after an MfaRequiredError
|
|
40
|
+
* const moved = await client.admin.rehomeProject(projectId, { targetOrg: 'ulu-labs', reason: 'OQ-4 row 7' });
|
|
41
|
+
* moved.rehome.to_org.slug; // 'ulu-labs'
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function rehomeProject(client: OpsHttpClient, projectId: string, input: AdminRehomeProjectInput): Promise<RehomeResponse>;
|
|
45
|
+
/**
|
|
46
|
+
* The reservation table — `GET /admin/projects/rehomes`: every vacated
|
|
47
|
+
* `(org, name)` address and where it redirects. Key-readable. This is the
|
|
48
|
+
* CURRENT redirect state, not the history — a reversal annihilates its row and
|
|
49
|
+
* a release deletes it; for "what happened" read {@link listProjectRehomeEvents}.
|
|
50
|
+
*
|
|
51
|
+
* `org` takes a UUID or a slug; `total` is the matching count, `returned` the page.
|
|
52
|
+
*
|
|
53
|
+
* @param client - HTTP client instance (a platform-admin key suffices)
|
|
54
|
+
* @param query - `{ projectId?, org?, since?, limit? }`
|
|
55
|
+
* @returns `{ data, total, returned }` — reservation rows, camelCase
|
|
56
|
+
*/
|
|
57
|
+
export declare function listProjectRehomes(client: OpsHttpClient, query?: ProjectRehomeListQuery): Promise<ProjectRehomeList>;
|
|
58
|
+
/**
|
|
59
|
+
* The append-only ledger (D21) — `GET /admin/projects/rehome-events`: every
|
|
60
|
+
* move, re-point, annihilation, degenerate drop, release and hard-delete
|
|
61
|
+
* release, written in the same transaction as the change; nothing the API
|
|
62
|
+
* offers removes a row. Key-readable. Pages by `seq` (insertion order) —
|
|
63
|
+
* `nextCursor` is the `seq` to continue strictly below; pass it back verbatim.
|
|
64
|
+
* This, not the reservation listing and not a script's own log, is what a
|
|
65
|
+
* migration reconciles against (spec §4.7 item 4).
|
|
66
|
+
*
|
|
67
|
+
* @param client - HTTP client instance (a platform-admin key suffices)
|
|
68
|
+
* @param query - `{ projectId?, org?, event?, since?, cursor?, limit? }`
|
|
69
|
+
* @returns `{ data, total, returned, hasMore, nextCursor }` — ledger rows, camelCase, newest `seq` first
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* let cursor: string | undefined;
|
|
73
|
+
* do {
|
|
74
|
+
* const page = await client.admin.listProjectRehomeEvents({ org: 'ulu-labs', event: 'moved', cursor });
|
|
75
|
+
* for (const ev of page.data) console.log(ev.seq, ev.projectName, ev.fromOrgId, '→', ev.toOrgId);
|
|
76
|
+
* cursor = page.nextCursor ?? undefined;
|
|
77
|
+
* } while (cursor);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function listProjectRehomeEvents(client: OpsHttpClient, query?: ProjectRehomeEventListQuery): Promise<ProjectRehomeEventList>;
|
|
81
|
+
/**
|
|
82
|
+
* Release a vacated address — `DELETE /admin/projects/rehomes/:id`. After
|
|
83
|
+
* this the old `(org, name)` is creatable again: a by-name writer there gets a
|
|
84
|
+
* NEW project instead of `410 PROJECT_REHOMED`. Deliberate, audited (`released`
|
|
85
|
+
* ledger row), never done by time. Session-only (D20): release is the step that
|
|
86
|
+
* empties the queryable record.
|
|
87
|
+
*
|
|
88
|
+
* @param client - HTTP client instance carrying a SESSION
|
|
89
|
+
* @param rehomeId - The reservation row id (from {@link listProjectRehomes}); a non-UUID is refused client-side
|
|
90
|
+
* @returns `{ released: true }`
|
|
91
|
+
* @throws {InputValidationError} If `rehomeId` is not a UUID
|
|
92
|
+
* @throws {ZodError} If the 200 body does not say `released: true` — the same signal every other
|
|
93
|
+
* shape mismatch in this SDK gives. Note the server sends 200 AFTER the row is gone, so a
|
|
94
|
+
* shape failure here means the release most likely HAPPENED; re-read `listProjectRehomes`
|
|
95
|
+
* before retrying (a retry answers 404).
|
|
96
|
+
*/
|
|
97
|
+
export declare function releaseProjectRehome(client: OpsHttpClient, rehomeId: string): Promise<{
|
|
98
|
+
released: true;
|
|
99
|
+
}>;
|
|
100
|
+
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/operations/admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EACV,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC5B,MAAM,oBAAoB,CAAC;AAS5B;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,cAAc,CAAC,CAOzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,KAAK,GAAE,sBAA2B,GACjC,OAAO,CAAC,iBAAiB,CAAC,CAO5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,KAAK,GAAE,2BAAgC,GACtC,OAAO,CAAC,sBAAsB,CAAC,CAUjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC,CAG7B"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { RehomeResponseSchema, ProjectRehomeListResponseSchema, ProjectRehomeEventListResponseSchema, } from '../types/rehome.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { validateAdminRehomeProjectInput, validateUuid } from '../config/validators.js';
|
|
4
|
+
/**
|
|
5
|
+
* Platform-admin project re-home surface (project-org-routing-and-rehome spec
|
|
6
|
+
* §4.1 D8, §4.7, D20, D21). Every call here requires `users.role = 'admin'` —
|
|
7
|
+
* a PLATFORM role, not an org role — and the two writes additionally require
|
|
8
|
+
* a login-issued SESSION (D20): a `ulr_` key, even an admin's, gets
|
|
9
|
+
* `403 SESSION_REQUIRED` (`isSessionRequiredError`). Log in with
|
|
10
|
+
* `OpsClient.login` (completing MFA via `loginWithTotp` if challenged) and the
|
|
11
|
+
* session bearer is what these calls send. There is deliberately no MCP tool
|
|
12
|
+
* for any of this.
|
|
13
|
+
*
|
|
14
|
+
* `admin.` is a namespace, not an escalation: the same client, the same auth
|
|
15
|
+
* strategy. If the credential cannot do it the server says so.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Move ANY project between ANY two orgs — `POST /admin/projects/:id/rehome`.
|
|
19
|
+
* No source-membership and no target-membership requirement (the platform role
|
|
20
|
+
* is the authority), so `reason` is REQUIRED: on this path the target org's
|
|
21
|
+
* only standing is the `rehome_in` audit row plus that text. Resolves the
|
|
22
|
+
* project by id UNSCOPED (the admin router has no org context) — the route
|
|
23
|
+
* takes a UUID and answers 400 to anything else, so unlike `projects.*` a
|
|
24
|
+
* NAME is refused here, client-side, before the request.
|
|
25
|
+
*
|
|
26
|
+
* Session-only (D20). Phase 4 of the spec runs this once per row of the OQ-4
|
|
27
|
+
* table, sequentially, with the row reference as `reason`. On THIS path a
|
|
28
|
+
* re-run over a finished row answers `same_org` (the lookup is by id, so the
|
|
29
|
+
* moved project is found wherever it is) — read it as "already done" via
|
|
30
|
+
* `rehomeRefusalReason`. That is not true of the member path, whose lookup is
|
|
31
|
+
* source-scoped (see `projects.rehome`).
|
|
32
|
+
*
|
|
33
|
+
* @param client - HTTP client instance carrying a SESSION
|
|
34
|
+
* @param projectId - Project UUID (a name is an `InputValidationError`)
|
|
35
|
+
* @param input - `{ targetOrg, reason }` — both required
|
|
36
|
+
* @returns The project after the move (`orgId` is the target) plus the `rehome` block
|
|
37
|
+
* @throws {InputValidationError} If `projectId` is not a UUID, `targetOrg` is not a slug, or `reason` is missing
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* await client.login(email, password); // or loginWithTotp after an MfaRequiredError
|
|
41
|
+
* const moved = await client.admin.rehomeProject(projectId, { targetOrg: 'ulu-labs', reason: 'OQ-4 row 7' });
|
|
42
|
+
* moved.rehome.to_org.slug; // 'ulu-labs'
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export async function rehomeProject(client, projectId, input) {
|
|
46
|
+
validateUuid(projectId, 'projectId');
|
|
47
|
+
const valid = validateAdminRehomeProjectInput(input);
|
|
48
|
+
return RehomeResponseSchema.parse(await client.post(`/admin/projects/${encodeURIComponent(projectId)}/rehome`, { target_org: valid.targetOrg, reason: valid.reason }));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The reservation table — `GET /admin/projects/rehomes`: every vacated
|
|
52
|
+
* `(org, name)` address and where it redirects. Key-readable. This is the
|
|
53
|
+
* CURRENT redirect state, not the history — a reversal annihilates its row and
|
|
54
|
+
* a release deletes it; for "what happened" read {@link listProjectRehomeEvents}.
|
|
55
|
+
*
|
|
56
|
+
* `org` takes a UUID or a slug; `total` is the matching count, `returned` the page.
|
|
57
|
+
*
|
|
58
|
+
* @param client - HTTP client instance (a platform-admin key suffices)
|
|
59
|
+
* @param query - `{ projectId?, org?, since?, limit? }`
|
|
60
|
+
* @returns `{ data, total, returned }` — reservation rows, camelCase
|
|
61
|
+
*/
|
|
62
|
+
export async function listProjectRehomes(client, query = {}) {
|
|
63
|
+
return ProjectRehomeListResponseSchema.parse(await client.request('GET', '/admin/projects/rehomes', rehomeListParams(query), { rawEnvelope: true }));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The append-only ledger (D21) — `GET /admin/projects/rehome-events`: every
|
|
67
|
+
* move, re-point, annihilation, degenerate drop, release and hard-delete
|
|
68
|
+
* release, written in the same transaction as the change; nothing the API
|
|
69
|
+
* offers removes a row. Key-readable. Pages by `seq` (insertion order) —
|
|
70
|
+
* `nextCursor` is the `seq` to continue strictly below; pass it back verbatim.
|
|
71
|
+
* This, not the reservation listing and not a script's own log, is what a
|
|
72
|
+
* migration reconciles against (spec §4.7 item 4).
|
|
73
|
+
*
|
|
74
|
+
* @param client - HTTP client instance (a platform-admin key suffices)
|
|
75
|
+
* @param query - `{ projectId?, org?, event?, since?, cursor?, limit? }`
|
|
76
|
+
* @returns `{ data, total, returned, hasMore, nextCursor }` — ledger rows, camelCase, newest `seq` first
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* let cursor: string | undefined;
|
|
80
|
+
* do {
|
|
81
|
+
* const page = await client.admin.listProjectRehomeEvents({ org: 'ulu-labs', event: 'moved', cursor });
|
|
82
|
+
* for (const ev of page.data) console.log(ev.seq, ev.projectName, ev.fromOrgId, '→', ev.toOrgId);
|
|
83
|
+
* cursor = page.nextCursor ?? undefined;
|
|
84
|
+
* } while (cursor);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export async function listProjectRehomeEvents(client, query = {}) {
|
|
88
|
+
const params = rehomeListParams(query);
|
|
89
|
+
if (query.event !== undefined)
|
|
90
|
+
params['event'] = query.event;
|
|
91
|
+
if (query.cursor !== undefined)
|
|
92
|
+
params['cursor'] = query.cursor;
|
|
93
|
+
return ProjectRehomeEventListResponseSchema.parse(await client.request('GET', '/admin/projects/rehome-events', params, { rawEnvelope: true }));
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Release a vacated address — `DELETE /admin/projects/rehomes/:id`. After
|
|
97
|
+
* this the old `(org, name)` is creatable again: a by-name writer there gets a
|
|
98
|
+
* NEW project instead of `410 PROJECT_REHOMED`. Deliberate, audited (`released`
|
|
99
|
+
* ledger row), never done by time. Session-only (D20): release is the step that
|
|
100
|
+
* empties the queryable record.
|
|
101
|
+
*
|
|
102
|
+
* @param client - HTTP client instance carrying a SESSION
|
|
103
|
+
* @param rehomeId - The reservation row id (from {@link listProjectRehomes}); a non-UUID is refused client-side
|
|
104
|
+
* @returns `{ released: true }`
|
|
105
|
+
* @throws {InputValidationError} If `rehomeId` is not a UUID
|
|
106
|
+
* @throws {ZodError} If the 200 body does not say `released: true` — the same signal every other
|
|
107
|
+
* shape mismatch in this SDK gives. Note the server sends 200 AFTER the row is gone, so a
|
|
108
|
+
* shape failure here means the release most likely HAPPENED; re-read `listProjectRehomes`
|
|
109
|
+
* before retrying (a retry answers 404).
|
|
110
|
+
*/
|
|
111
|
+
export async function releaseProjectRehome(client, rehomeId) {
|
|
112
|
+
validateUuid(rehomeId, 'rehomeId');
|
|
113
|
+
return ReleaseResponseSchema.parse(await client.delete(`/admin/projects/rehomes/${encodeURIComponent(rehomeId)}`));
|
|
114
|
+
}
|
|
115
|
+
/** `DELETE /admin/projects/rehomes/:id` answers `{ data: { released: true } }`; anything else is a contract break. */
|
|
116
|
+
const ReleaseResponseSchema = z.object({ released: z.literal(true) });
|
|
117
|
+
/** Shared filter serialisation for the two listings — snake_case on the wire (`project_id`), strings throughout. */
|
|
118
|
+
function rehomeListParams(query) {
|
|
119
|
+
const params = {};
|
|
120
|
+
if (query.projectId !== undefined)
|
|
121
|
+
params['project_id'] = query.projectId;
|
|
122
|
+
if (query.org !== undefined)
|
|
123
|
+
params['org'] = query.org;
|
|
124
|
+
if (query.since !== undefined)
|
|
125
|
+
params['since'] = query.since;
|
|
126
|
+
if (query.limit !== undefined)
|
|
127
|
+
params['limit'] = String(query.limit);
|
|
128
|
+
return params;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/operations/admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OpsHttpClient } from '../http/http-client.js';
|
|
2
|
-
import type { RegisterInput, LoginInput, LoginResponse, RegisterResponse, UpdateProfileInput, ChangePasswordInput, ResetPasswordInput, CreateApiKeyInput, ApiKeyCreatedResponse, PublicApiKey, PublicSession, AuthUser, PublicUser } from '../types/auth.js';
|
|
2
|
+
import type { RegisterInput, LoginInput, LoginResponse, TotpLoginInput, RegisterResponse, UpdateProfileInput, ChangePasswordInput, ResetPasswordInput, CreateApiKeyInput, ApiKeyCreatedResponse, PublicApiKey, PublicSession, AuthUser, PublicUser } from '../types/auth.js';
|
|
3
3
|
import type { MessageResponse } from '../types/responses.js';
|
|
4
4
|
/**
|
|
5
5
|
* Register a new user account. Does not require authentication.
|
|
@@ -23,8 +23,28 @@ export declare function register(client: OpsHttpClient, input: RegisterInput): P
|
|
|
23
23
|
* @returns `{ user, sessionToken }` — token must be manually installed on the client
|
|
24
24
|
* @throws {InputValidationError} If email or password is missing
|
|
25
25
|
* @throws {UnauthorizedError} If credentials are invalid
|
|
26
|
+
* @throws {MfaRequiredError} If the account has TOTP or a passkey enrolled — the API answered a
|
|
27
|
+
* challenge, not a session; complete it with `totpLogin` / `OpsClient.loginWithTotp`
|
|
26
28
|
*/
|
|
27
29
|
export declare function login(client: OpsHttpClient, input: LoginInput): Promise<LoginResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Complete an MFA-challenged login with a TOTP code (`POST /auth/totp/login`).
|
|
32
|
+
* Returns the same `{ user, sessionToken, expiresAt }` a password login does.
|
|
33
|
+
* Like `login`, this only RETURNS the session — `OpsClient.loginWithTotp`
|
|
34
|
+
* installs it.
|
|
35
|
+
*
|
|
36
|
+
* **The challenge is single-use and is consumed BEFORE the code is checked**
|
|
37
|
+
* (`totp-service.verifyLogin`: consume, then verify). A wrong code therefore
|
|
38
|
+
* burns the token: retrying `totpLogin` with the same `mfaChallengeToken` is a
|
|
39
|
+
* 401 every time. Recovery is a fresh `login()` for a fresh challenge.
|
|
40
|
+
*
|
|
41
|
+
* @param client - HTTP client instance
|
|
42
|
+
* @param input - `{ mfaChallengeToken, code, rememberMe? }`
|
|
43
|
+
* @returns `{ user, sessionToken, expiresAt }` — token must be manually installed on the client
|
|
44
|
+
* @throws {InputValidationError} If the token is empty or the code is not six digits
|
|
45
|
+
* @throws {UnauthorizedError} If the code is wrong, or the challenge expired or was already consumed
|
|
46
|
+
*/
|
|
47
|
+
export declare function totpLogin(client: OpsHttpClient, input: TotpLoginInput): Promise<LoginResponse>;
|
|
28
48
|
/**
|
|
29
49
|
* Revoke all sessions for the current user (not just the current session).
|
|
30
50
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/operations/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,UAAU,EACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/operations/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/operations/auth.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { AuthUserResponseSchema, PublicUserResponseSchema, LoginResponseSchema, RegisterResponseSchema, PublicApiKeyResponseSchema, ApiKeyCreatedResponseSchema, PublicSessionResponseSchema, MessageResponseSchema, } from '../types/response-schemas.js';
|
|
3
|
-
import { validateRegisterInput, validateLoginInput, validateUpdateProfileInput, validateChangePasswordInput, validateResetPasswordInput, validateSetPasswordInput, validateCreateApiKeyInput, } from '../config/validators.js';
|
|
2
|
+
import { AuthUserResponseSchema, PublicUserResponseSchema, LoginResponseSchema, MfaChallengeResponseSchema, RegisterResponseSchema, PublicApiKeyResponseSchema, ApiKeyCreatedResponseSchema, PublicSessionResponseSchema, MessageResponseSchema, } from '../types/response-schemas.js';
|
|
3
|
+
import { validateRegisterInput, validateLoginInput, validateTotpLoginInput, validateUpdateProfileInput, validateChangePasswordInput, validateResetPasswordInput, validateSetPasswordInput, validateCreateApiKeyInput, } from '../config/validators.js';
|
|
4
|
+
import { MfaRequiredError } from '../errors/errors.js';
|
|
4
5
|
const ProfileResponseSchema = z.object({ user: PublicUserResponseSchema });
|
|
5
6
|
/**
|
|
6
7
|
* Register a new user account. Does not require authentication.
|
|
@@ -27,10 +28,55 @@ export async function register(client, input) {
|
|
|
27
28
|
* @returns `{ user, sessionToken }` — token must be manually installed on the client
|
|
28
29
|
* @throws {InputValidationError} If email or password is missing
|
|
29
30
|
* @throws {UnauthorizedError} If credentials are invalid
|
|
31
|
+
* @throws {MfaRequiredError} If the account has TOTP or a passkey enrolled — the API answered a
|
|
32
|
+
* challenge, not a session; complete it with `totpLogin` / `OpsClient.loginWithTotp`
|
|
30
33
|
*/
|
|
31
34
|
export async function login(client, input) {
|
|
32
35
|
validateLoginInput(input);
|
|
33
|
-
|
|
36
|
+
const body = await client.post('/auth/login', input, { skipAuth: true });
|
|
37
|
+
return parseLoginOrChallenge(body);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Complete an MFA-challenged login with a TOTP code (`POST /auth/totp/login`).
|
|
41
|
+
* Returns the same `{ user, sessionToken, expiresAt }` a password login does.
|
|
42
|
+
* Like `login`, this only RETURNS the session — `OpsClient.loginWithTotp`
|
|
43
|
+
* installs it.
|
|
44
|
+
*
|
|
45
|
+
* **The challenge is single-use and is consumed BEFORE the code is checked**
|
|
46
|
+
* (`totp-service.verifyLogin`: consume, then verify). A wrong code therefore
|
|
47
|
+
* burns the token: retrying `totpLogin` with the same `mfaChallengeToken` is a
|
|
48
|
+
* 401 every time. Recovery is a fresh `login()` for a fresh challenge.
|
|
49
|
+
*
|
|
50
|
+
* @param client - HTTP client instance
|
|
51
|
+
* @param input - `{ mfaChallengeToken, code, rememberMe? }`
|
|
52
|
+
* @returns `{ user, sessionToken, expiresAt }` — token must be manually installed on the client
|
|
53
|
+
* @throws {InputValidationError} If the token is empty or the code is not six digits
|
|
54
|
+
* @throws {UnauthorizedError} If the code is wrong, or the challenge expired or was already consumed
|
|
55
|
+
*/
|
|
56
|
+
export async function totpLogin(client, input) {
|
|
57
|
+
const valid = validateTotpLoginInput(input);
|
|
58
|
+
return LoginResponseSchema.parse(await client.post('/auth/totp/login', {
|
|
59
|
+
mfa_challenge_token: valid.mfaChallengeToken,
|
|
60
|
+
code: valid.code,
|
|
61
|
+
...(valid.rememberMe !== undefined ? { rememberMe: valid.rememberMe } : {}),
|
|
62
|
+
}, { skipAuth: true }));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A 200 from `/auth/login` is one of two shapes; the challenge is tried FIRST
|
|
66
|
+
* because it is the narrower literal, and a session body can never carry
|
|
67
|
+
* `mfa_required: true`. Anything else falls through to the strict session
|
|
68
|
+
* parse, whose ZodError names what was actually missing.
|
|
69
|
+
*/
|
|
70
|
+
function parseLoginOrChallenge(body) {
|
|
71
|
+
const challenge = MfaChallengeResponseSchema.safeParse(body);
|
|
72
|
+
if (challenge.success) {
|
|
73
|
+
throw new MfaRequiredError({
|
|
74
|
+
mfaChallengeToken: challenge.data.mfa_challenge_token,
|
|
75
|
+
expiresAt: challenge.data.expires_at,
|
|
76
|
+
mfaMethods: challenge.data.mfa_methods,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return LoginResponseSchema.parse(body);
|
|
34
80
|
}
|
|
35
81
|
/**
|
|
36
82
|
* Revoke all sessions for the current user (not just the current session).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/operations/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/operations/auth.ts"],"names":[],"mappings":"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"}
|