@uluops/ops-sdk 6.3.1 → 6.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.
- package/CHANGELOG.md +69 -0
- package/README.md +273 -2
- package/dist/client.d.ts +110 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +94 -5
- package/dist/client.js.map +1 -1
- package/dist/config/constants.d.ts +1 -1
- package/dist/config/generated-version.d.ts +1 -1
- package/dist/config/generated-version.js +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 +25 -4
- package/dist/config/workspace-org.d.ts.map +1 -1
- package/dist/config/workspace-org.js +71 -18
- package/dist/config/workspace-org.js.map +1 -1
- package/dist/errors/errors.d.ts +71 -0
- package/dist/errors/errors.d.ts.map +1 -1
- package/dist/errors/errors.js +99 -0
- package/dist/errors/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- 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 +45 -0
- package/dist/operations/orgs.d.ts.map +1 -0
- package/dist/operations/orgs.js +57 -0
- package/dist/operations/orgs.js.map +1 -0
- package/dist/operations/projects.d.ts +74 -0
- package/dist/operations/projects.d.ts.map +1 -1
- package/dist/operations/projects.js +115 -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/log.d.ts +410 -0
- package/dist/types/log.d.ts.map +1 -0
- package/dist/types/log.js +191 -0
- package/dist/types/log.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
package/dist/errors/errors.d.ts
CHANGED
|
@@ -100,4 +100,75 @@ export declare function isOrgAccessDeniedError(err: unknown): err is _SdkApiErro
|
|
|
100
100
|
export declare function isProjectRehomedError(err: unknown): err is _SdkApiError & {
|
|
101
101
|
details: ProjectRehomedDetails;
|
|
102
102
|
};
|
|
103
|
+
/**
|
|
104
|
+
* 403 — the route is session-only (D20): platform-admin writes that mint or
|
|
105
|
+
* re-point identity, and the two cross-tenant project moves, refuse a `ulr_`
|
|
106
|
+
* key even when its user is a platform admin. Terminal for a key-authenticated
|
|
107
|
+
* client: log in (`OpsClient.login`, completing MFA with `loginWithTotp` if
|
|
108
|
+
* challenged) and retry with the session — never by minting another key.
|
|
109
|
+
*/
|
|
110
|
+
export declare const SESSION_REQUIRED: "SESSION_REQUIRED";
|
|
111
|
+
/** 403 — the caller lacks the PLATFORM role (`users.role`) the admin path requires; distinct from the org-role codes above. */
|
|
112
|
+
export declare const INSUFFICIENT_ROLE: "INSUFFICIENT_ROLE";
|
|
113
|
+
/** Type guard: session-only route refused an API key (403 `SESSION_REQUIRED`). Terminal for key auth. */
|
|
114
|
+
export declare function isSessionRequiredError(err: unknown): err is _SdkApiError;
|
|
115
|
+
/** Type guard: the caller's PLATFORM role is below what the admin path requires (403 `INSUFFICIENT_ROLE`). Terminal — no org argument changes it. */
|
|
116
|
+
export declare function isInsufficientRoleError(err: unknown): err is _SdkApiError;
|
|
117
|
+
/**
|
|
118
|
+
* The refusal reasons a re-home can answer with, as `details.reason` on a
|
|
119
|
+
* 400 (`VALIDATION_ERROR`) or 409 (`CONFLICT`). Enumerated here because the
|
|
120
|
+
* Phase 4 runbook (spec §4.7 item 3) assigns each a disposition, and a script
|
|
121
|
+
* that switches on a string it typed itself will misspell one:
|
|
122
|
+
*
|
|
123
|
+
* - `same_org` — already there. Idempotent re-run over a finished row; count as done.
|
|
124
|
+
* - `moved_during_request` / `deadlock_retry` / `concurrent_modification` — re-read and retry once.
|
|
125
|
+
* - `name_collision` / `soft_deleted_conflict` / `rehomed_away_conflict` — skip and report.
|
|
126
|
+
* - `export_in_progress` — an export job holds either org; wait, then retry.
|
|
127
|
+
* - `project_soft_deleted` / `project_has_no_org` — the source row is not movable as-is; stop and look.
|
|
128
|
+
*/
|
|
129
|
+
export declare const REHOME_REFUSAL_REASONS: readonly ["same_org", "moved_during_request", "deadlock_retry", "concurrent_modification", "name_collision", "soft_deleted_conflict", "rehomed_away_conflict", "export_in_progress", "project_soft_deleted", "project_has_no_org"];
|
|
130
|
+
export type RehomeRefusalReason = (typeof REHOME_REFUSAL_REASONS)[number];
|
|
131
|
+
/**
|
|
132
|
+
* The re-home refusal reason carried by a rejection, or `null` when the error
|
|
133
|
+
* is not one of the enumerated re-home refusals (a 403 org code, a 402
|
|
134
|
+
* `PROJECT_LIMIT`, a network failure). Reads `details.reason`; an unknown
|
|
135
|
+
* reason string returns null rather than a widened type — a new server reason
|
|
136
|
+
* should reach the caller as "not one I know", not as a silently-handled case.
|
|
137
|
+
*
|
|
138
|
+
* `null` therefore means "not a re-home refusal I can name", NOT "safe to
|
|
139
|
+
* retry": a `TimeoutError` / `NetworkError` after the server committed the
|
|
140
|
+
* move also reads `null`, and a blind retry on the admin path answers
|
|
141
|
+
* `same_org` (fine) while on the member path it answers 404 (see
|
|
142
|
+
* `projects.rehome`). Branch on `isTimeoutError` / `isNetworkError` first.
|
|
143
|
+
*/
|
|
144
|
+
export declare function rehomeRefusalReason(err: unknown): RehomeRefusalReason | null;
|
|
145
|
+
/**
|
|
146
|
+
* Thrown by `OpsClient.login` / `auth.login` when the account has MFA enabled:
|
|
147
|
+
* the API answers `200 { mfa_required: true, mfa_challenge_token, ... }` and no
|
|
148
|
+
* session. Until 6.4.0 this surfaced as a raw `ZodError` on `sessionToken`,
|
|
149
|
+
* which made the SDK unable to log in ANY MFA account. Complete the login with
|
|
150
|
+
* `OpsClient.loginWithTotp(err.mfaChallengeToken, code)` before the challenge
|
|
151
|
+
* expires (`expiresAt`). WebAuthn completion is not offered by this SDK.
|
|
152
|
+
*
|
|
153
|
+
* **The token is single-use and is consumed before the code is verified** —
|
|
154
|
+
* a mistyped code burns it; do not loop on `loginWithTotp` with the same
|
|
155
|
+
* token, call `login()` again for a new challenge. And this error is raised
|
|
156
|
+
* only by `login()` / `auth.login()`: a client constructed with
|
|
157
|
+
* `{ email, password }` (or autoloaded credentials) logs in inside sdk-core,
|
|
158
|
+
* which cannot see the challenge and surfaces a generic `UnauthorizedError`
|
|
159
|
+
* — MFA accounts must use the two-step `login()` → `loginWithTotp()` path.
|
|
160
|
+
*/
|
|
161
|
+
export declare class MfaRequiredError extends Error {
|
|
162
|
+
readonly name = "MfaRequiredError";
|
|
163
|
+
readonly mfaChallengeToken: string;
|
|
164
|
+
readonly expiresAt: string;
|
|
165
|
+
readonly mfaMethods: readonly string[];
|
|
166
|
+
constructor(challenge: {
|
|
167
|
+
mfaChallengeToken: string;
|
|
168
|
+
expiresAt: string;
|
|
169
|
+
mfaMethods: readonly string[];
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** Type guard for {@link MfaRequiredError}. */
|
|
173
|
+
export declare function isMfaRequiredError(err: unknown): err is MfaRequiredError;
|
|
103
174
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,WAAW,IAAI,WAAW,EAC1B,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,IAAI,aAAa,EAC9B,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,GAAG,uBAAuB,CAAC;IAC5E,kFAAkF;IAClF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QACpC,MAAM,EAAE,cAAc,GAAG,eAAe,GAAG,uBAAuB,CAAC;QACnE,kBAAkB,EAAE,MAAM,CAAC;QAC3B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,GAAG,EAAE,OAAO,CAAC;QACb,aAAa,EAAE,OAAO,CAAC;KACxB;CASF;AAMD,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAG,uBAAgC,CAAC;AACtE,sHAAsH;AACtH,eAAO,MAAM,iBAAiB,EAAG,mBAA4B,CAAC;AAC9D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAG,iBAA0B,CAAC;AAE1D,8EAA8E;AAC9E,MAAM,WAAW,0BAA0B;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,+DAA+D;AAC/D,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAMD,8HAA8H;AAC9H,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY,GAAG;IAAE,OAAO,CAAC,EAAE,0BAA0B,CAAA;CAAE,CAEvH;AAED,oHAAoH;AACpH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY,CAExE;AAED,sHAAsH;AACtH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY,GAAG;IAAE,OAAO,EAAE,qBAAqB,CAAA;CAAE,CAI5G"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/errors/errors.js
CHANGED
|
@@ -95,4 +95,103 @@ export function isProjectRehomedError(err) {
|
|
|
95
95
|
const d = err.details;
|
|
96
96
|
return typeof d?.target_org?.slug === 'string' && typeof d.project_id === 'string';
|
|
97
97
|
}
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Re-home surfaces (spec §4, 6.4.0)
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
/**
|
|
102
|
+
* 403 — the route is session-only (D20): platform-admin writes that mint or
|
|
103
|
+
* re-point identity, and the two cross-tenant project moves, refuse a `ulr_`
|
|
104
|
+
* key even when its user is a platform admin. Terminal for a key-authenticated
|
|
105
|
+
* client: log in (`OpsClient.login`, completing MFA with `loginWithTotp` if
|
|
106
|
+
* challenged) and retry with the session — never by minting another key.
|
|
107
|
+
*/
|
|
108
|
+
export const SESSION_REQUIRED = 'SESSION_REQUIRED';
|
|
109
|
+
/** 403 — the caller lacks the PLATFORM role (`users.role`) the admin path requires; distinct from the org-role codes above. */
|
|
110
|
+
export const INSUFFICIENT_ROLE = 'INSUFFICIENT_ROLE';
|
|
111
|
+
/** Type guard: session-only route refused an API key (403 `SESSION_REQUIRED`). Terminal for key auth. */
|
|
112
|
+
export function isSessionRequiredError(err) {
|
|
113
|
+
return hasCode(err, SESSION_REQUIRED);
|
|
114
|
+
}
|
|
115
|
+
/** Type guard: the caller's PLATFORM role is below what the admin path requires (403 `INSUFFICIENT_ROLE`). Terminal — no org argument changes it. */
|
|
116
|
+
export function isInsufficientRoleError(err) {
|
|
117
|
+
return hasCode(err, INSUFFICIENT_ROLE);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The refusal reasons a re-home can answer with, as `details.reason` on a
|
|
121
|
+
* 400 (`VALIDATION_ERROR`) or 409 (`CONFLICT`). Enumerated here because the
|
|
122
|
+
* Phase 4 runbook (spec §4.7 item 3) assigns each a disposition, and a script
|
|
123
|
+
* that switches on a string it typed itself will misspell one:
|
|
124
|
+
*
|
|
125
|
+
* - `same_org` — already there. Idempotent re-run over a finished row; count as done.
|
|
126
|
+
* - `moved_during_request` / `deadlock_retry` / `concurrent_modification` — re-read and retry once.
|
|
127
|
+
* - `name_collision` / `soft_deleted_conflict` / `rehomed_away_conflict` — skip and report.
|
|
128
|
+
* - `export_in_progress` — an export job holds either org; wait, then retry.
|
|
129
|
+
* - `project_soft_deleted` / `project_has_no_org` — the source row is not movable as-is; stop and look.
|
|
130
|
+
*/
|
|
131
|
+
export const REHOME_REFUSAL_REASONS = [
|
|
132
|
+
'same_org',
|
|
133
|
+
'moved_during_request',
|
|
134
|
+
'deadlock_retry',
|
|
135
|
+
'concurrent_modification',
|
|
136
|
+
'name_collision',
|
|
137
|
+
'soft_deleted_conflict',
|
|
138
|
+
'rehomed_away_conflict',
|
|
139
|
+
'export_in_progress',
|
|
140
|
+
'project_soft_deleted',
|
|
141
|
+
'project_has_no_org',
|
|
142
|
+
];
|
|
143
|
+
/**
|
|
144
|
+
* The re-home refusal reason carried by a rejection, or `null` when the error
|
|
145
|
+
* is not one of the enumerated re-home refusals (a 403 org code, a 402
|
|
146
|
+
* `PROJECT_LIMIT`, a network failure). Reads `details.reason`; an unknown
|
|
147
|
+
* reason string returns null rather than a widened type — a new server reason
|
|
148
|
+
* should reach the caller as "not one I know", not as a silently-handled case.
|
|
149
|
+
*
|
|
150
|
+
* `null` therefore means "not a re-home refusal I can name", NOT "safe to
|
|
151
|
+
* retry": a `TimeoutError` / `NetworkError` after the server committed the
|
|
152
|
+
* move also reads `null`, and a blind retry on the admin path answers
|
|
153
|
+
* `same_org` (fine) while on the member path it answers 404 (see
|
|
154
|
+
* `projects.rehome`). Branch on `isTimeoutError` / `isNetworkError` first.
|
|
155
|
+
*/
|
|
156
|
+
export function rehomeRefusalReason(err) {
|
|
157
|
+
if (!(err instanceof _SdkApiError))
|
|
158
|
+
return null;
|
|
159
|
+
const reason = err.details?.reason;
|
|
160
|
+
return typeof reason === 'string' && REHOME_REFUSAL_REASONS.includes(reason)
|
|
161
|
+
? reason
|
|
162
|
+
: null;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Thrown by `OpsClient.login` / `auth.login` when the account has MFA enabled:
|
|
166
|
+
* the API answers `200 { mfa_required: true, mfa_challenge_token, ... }` and no
|
|
167
|
+
* session. Until 6.4.0 this surfaced as a raw `ZodError` on `sessionToken`,
|
|
168
|
+
* which made the SDK unable to log in ANY MFA account. Complete the login with
|
|
169
|
+
* `OpsClient.loginWithTotp(err.mfaChallengeToken, code)` before the challenge
|
|
170
|
+
* expires (`expiresAt`). WebAuthn completion is not offered by this SDK.
|
|
171
|
+
*
|
|
172
|
+
* **The token is single-use and is consumed before the code is verified** —
|
|
173
|
+
* a mistyped code burns it; do not loop on `loginWithTotp` with the same
|
|
174
|
+
* token, call `login()` again for a new challenge. And this error is raised
|
|
175
|
+
* only by `login()` / `auth.login()`: a client constructed with
|
|
176
|
+
* `{ email, password }` (or autoloaded credentials) logs in inside sdk-core,
|
|
177
|
+
* which cannot see the challenge and surfaces a generic `UnauthorizedError`
|
|
178
|
+
* — MFA accounts must use the two-step `login()` → `loginWithTotp()` path.
|
|
179
|
+
*/
|
|
180
|
+
export class MfaRequiredError extends Error {
|
|
181
|
+
name = 'MfaRequiredError';
|
|
182
|
+
mfaChallengeToken;
|
|
183
|
+
expiresAt;
|
|
184
|
+
mfaMethods;
|
|
185
|
+
constructor(challenge) {
|
|
186
|
+
super(`Login requires a second factor (${challenge.mfaMethods.join(', ') || 'unknown method'}); ` +
|
|
187
|
+
'complete it with loginWithTotp(mfaChallengeToken, code) before the challenge expires');
|
|
188
|
+
this.mfaChallengeToken = challenge.mfaChallengeToken;
|
|
189
|
+
this.expiresAt = challenge.expiresAt;
|
|
190
|
+
this.mfaMethods = challenge.mfaMethods;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** Type guard for {@link MfaRequiredError}. */
|
|
194
|
+
export function isMfaRequiredError(err) {
|
|
195
|
+
return err instanceof MfaRequiredError;
|
|
196
|
+
}
|
|
98
197
|
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,WAAW,IAAI,WAAW,EAC1B,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,IAAI,aAAa,EAC9B,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,sBAAsB;AACtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,mFAAmF;IAC1E,MAAM,CAA6D;IAC5E,kFAAkF;IACzE,kBAAkB,CAAS;IACpC,0EAA0E;IACjE,gBAAgB,CAAgB;IACzC,yEAAyE;IAChE,GAAG,CAAU;IACtB,qEAAqE;IAC5D,aAAa,CAAU;IAEhC,YAAY,OAAe,EAAE,OAM5B;QACC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;QACrD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QACjD,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC7C,CAAC;CACF;AAED,8EAA8E;AAC9E,2DAA2D;AAC3D,8EAA8E;AAE9E,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAgC,CAAC;AACtE,sHAAsH;AACtH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAA4B,CAAC;AAC9D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,iBAA0B,CAAC;AAoB1D,SAAS,OAAO,CAAC,GAAY,EAAE,IAAY;IACzC,OAAO,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC;AAC1D,CAAC;AAED,8HAA8H;AAC9H,MAAM,UAAU,0BAA0B,CAAC,GAAY;IACrD,OAAO,OAAO,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;AAC7C,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,sBAAsB,CAAC,GAAY;IACjD,OAAO,OAAO,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;AACzC,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,qBAAqB,CAAC,GAAY;IAChD,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,MAAM,CAAC,GAAG,GAAG,CAAC,OAAqD,CAAC;IACpE,OAAO,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC;AACrF,CAAC"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors/errors.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,5 +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
|
+
export { resolveWorkspaceOrg, findWorkspaceOrgFile, readWorkspaceOrgFile, readWorkspaceFile, WORKSPACE_ORG_FILE, PERSONAL_ORG_SENTINEL, type WorkspaceFile, type WorkspaceOrgResolution, type WorkspaceOrgSource, type ResolveWorkspaceOrgOptions, } from './config/workspace-org.js';
|
|
20
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,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,GAChC,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -21,5 +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
|
+
export { resolveWorkspaceOrg, findWorkspaceOrgFile, readWorkspaceOrgFile, readWorkspaceFile, WORKSPACE_ORG_FILE, PERSONAL_ORG_SENTINEL, } from './config/workspace-org.js';
|
|
25
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,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,GAKtB,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).
|