@truenas/api-client 3.0.4 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -12798,6 +12798,49 @@ declare class TrueNasApi<D extends ApiDirectoryShape = BaseApiDirectory> {
12798
12798
  private initializeJobEventsSubscription;
12799
12799
  }
12800
12800
 
12801
+ /**
12802
+ * Response from the /api/versions endpoint
12803
+ * Returns an array of version strings directly
12804
+ * Example: ["v25.10.0", "v25.10.1", "v26.0.0"]
12805
+ */
12806
+ type ApiVersionResponse = string[];
12807
+ /**
12808
+ * Parsed API version information
12809
+ *
12810
+ * Version format:
12811
+ * - Legacy (v25.x): vYY.MM.PATCH (e.g., v25.10.0 = October 2025, patch 0)
12812
+ * - New (v26+): vYY.MINOR.PATCH (e.g., v26.0.0 = 2026, minor 0, patch 0)
12813
+ *
12814
+ * Note: The second segment has different semantics based on the year:
12815
+ * - Year 25: month (1-12)
12816
+ * - Year 26+: minor version (0-99)
12817
+ */
12818
+ interface ApiVersion {
12819
+ /** Full version string (e.g., "v26.0.0") */
12820
+ version: string;
12821
+ /** Two-digit year (e.g., 26 = 2026) */
12822
+ year: number;
12823
+ /**
12824
+ * Second version segment (semantics depend on year):
12825
+ * - For v25.x: month (1-12, e.g., 10 = October)
12826
+ * - For v26+: minor version (0-99)
12827
+ */
12828
+ minor: number;
12829
+ /** Patch version number (e.g., 0, 1, 2) */
12830
+ patch: number;
12831
+ /** WebSocket path for this version (e.g., "/api/v26.0.0") */
12832
+ websocketPath: string;
12833
+ }
12834
+ /**
12835
+ * Version compatibility status
12836
+ */
12837
+ declare enum VersionCompatibility {
12838
+ Compatible = "compatible",
12839
+ TooOld = "too-old",
12840
+ TooNew = "too-new",
12841
+ Invalid = "invalid"
12842
+ }
12843
+
12801
12844
  interface ApiKeyCreate {
12802
12845
  id: number;
12803
12846
  key: string;
@@ -12808,6 +12851,20 @@ interface ApiKeyCreate {
12808
12851
  declare enum UserRole {
12809
12852
  FullAdmin = "FULL_ADMIN"
12810
12853
  }
12854
+ /**
12855
+ * A role as middleware reports it.
12856
+ *
12857
+ * `UserRole` names only the role this client itself had a use for. Middleware
12858
+ * defines many more — `SHARING_ADMIN`, `READONLY_ADMIN` and so on — and this
12859
+ * client does not enumerate them, because it no longer makes any decision from
12860
+ * a role and would only be maintaining a second copy of someone else's list.
12861
+ *
12862
+ * Widened to `string` so a consumer can compare against the roles it cares
12863
+ * about without a cast, while `UserRole` still autocompletes. Consumers are
12864
+ * where role policy lives now, so the type they are handed has to admit the
12865
+ * roles they will actually test for.
12866
+ */
12867
+ type UserRoleName = UserRole | (string & {});
12811
12868
 
12812
12869
  interface UserPreferences {
12813
12870
  language: string;
@@ -12824,6 +12881,24 @@ interface AuthResponse {
12824
12881
  response_type: AuthResponseType;
12825
12882
  username?: string;
12826
12883
  authenticator?: 'LEVEL_1' | 'LEVEL_2' | 'LEVEL_3';
12884
+ /**
12885
+ * A token for re-authenticating without credentials.
12886
+ *
12887
+ * Absent below v26: `AuthRespSuccess` there declares only `response_type`,
12888
+ * `user_info` and `authenticator`. From v26 it is always present and is
12889
+ * `null` when no token was minted — because none was asked for, or because
12890
+ * the session cannot have one. Middleware refuses for a session authenticated
12891
+ * by a one-time *password* (`auth.generate_onetime_password`), which is not
12892
+ * the same thing as 2FA despite this codebase spelling 2FA "OTP" throughout.
12893
+ *
12894
+ * A 2FA account gets `null` for a different reason, and it is this client's
12895
+ * doing rather than the server's: the password request carrying the option is
12896
+ * answered `OTP_REQUIRED` before anything is minted, and `loginWithOtp` does
12897
+ * not send `login_options` on the second step. Middleware would honour it
12898
+ * there — `auth.login_ex_continue` re-enters `login_ex`, and a 2FA session
12899
+ * may hold a token — so this is a gap to close, not a limit to work around.
12900
+ */
12901
+ reconnect_token?: string | null;
12827
12902
  max_session_age?: number;
12828
12903
  max_inactivity?: number;
12829
12904
  urls?: string[];
@@ -12835,7 +12910,7 @@ interface AuthResponse {
12835
12910
  groups: number[];
12836
12911
  privilege: {
12837
12912
  roles: {
12838
- $set: UserRole[];
12913
+ $set: UserRoleName[];
12839
12914
  };
12840
12915
  };
12841
12916
  two_factor_auth_configured: boolean;
@@ -12874,9 +12949,17 @@ interface AuthResponse {
12874
12949
  * TrueNAS authenticator using the JSON-RPC 2.0 protocol.
12875
12950
  *
12876
12951
  * It handles authentication using the JSON-RPC 2.0 message format.
12952
+ *
12953
+ * Authentication only: any credential middleware accepts logs in here, whatever
12954
+ * roles it carries. No path checks privilege, and that is the design — the
12955
+ * appliance authorizes every privileged call on its own, and which roles a given
12956
+ * product requires is that product's policy, not this client's. Consumers who
12957
+ * need one read `user_info.privilege.roles` off the response and enforce it
12958
+ * themselves; embedding a rule here would impose it on every consumer at once.
12877
12959
  */
12878
12960
  declare class TrueNasAuthenticator {
12879
12961
  private connection;
12962
+ private readonly version?;
12880
12963
  static readonly DefaultSessionLifetime = 300;
12881
12964
  /**
12882
12965
  * whether or not the system is currently authenticated and accessible.
@@ -12896,9 +12979,94 @@ declare class TrueNasAuthenticator {
12896
12979
  key: string;
12897
12980
  };
12898
12981
  sessionLifetime: number;
12899
- constructor(connection: TrueNasConnection);
12982
+ /**
12983
+ * Claimed by each login when it sends and checked when its answer lands: a
12984
+ * difference means another login or a logout was issued in between, so this
12985
+ * answer is stale and must not write session state. Responses on one socket
12986
+ * are not ordered, which is why arrival is not enough to make an answer
12987
+ * current.
12988
+ *
12989
+ * `logout()` bumps it without claiming one. It has no answer to guard —
12990
+ * it settles its own state at the call — and bumping is what invalidates the
12991
+ * logins already on the wire that a logout is meant to override.
12992
+ */
12993
+ private authEpoch;
12994
+ /**
12995
+ * Caller-issued logins still awaiting an answer, keyed by the epoch each
12996
+ * claimed. The value is whether its frame has been written to a socket yet.
12997
+ *
12998
+ * The auto-relogin below defers while any entry exists. It is this class
12999
+ * retrying a cached credential, not a request anyone made, so it must never
13000
+ * outrank an explicit login — and it would: `TrueNasConnection.send` holds a
13001
+ * frame through an outage rather than dropping it, so a login submitted while
13002
+ * the socket is down is still pending when `opened` fires, and a relogin
13003
+ * claiming the newer epoch has that login answered `LoginSuperseded` while the
13004
+ * client authenticates as the previously cached account.
13005
+ *
13006
+ * Keyed rather than counted, because a count cannot say *which* login a
13007
+ * removal belongs to: a login torn down by its caller would retire a slot
13008
+ * belonging to a different login that is still waiting, and the retry would
13009
+ * overtake it again. Identity also makes a double-subscribed login harmless.
13010
+ */
13011
+ private liveCallerLogins;
13012
+ /** True only while the constructor's relogin is being constructed. */
13013
+ private reloginInProgress;
13014
+ constructor(connection: TrueNasConnection, version?: ApiVersion | undefined);
13015
+ /**
13016
+ * `login_options` asking for a reconnect token, when the server understands it.
13017
+ *
13018
+ * Omitted below v26. `AuthCommonOptions` is `additionalProperties: false`
13019
+ * there and has only `user_info`, so sending the member is a validation
13020
+ * error, not an ignored field — it would fail login outright on the oldest
13021
+ * version this client supports.
13022
+ */
13023
+ /**
13024
+ * Two things this does not do, both deliberate and both worth knowing.
13025
+ *
13026
+ * There is no way for a consumer to decline: every v26+ password login now
13027
+ * mints a single-use credential carrying that session's roles, whether or not
13028
+ * the caller wants one. And the auto-relogin in the constructor subscribes
13029
+ * with no observer, so the token it mints is dropped — a caller reconnecting
13030
+ * repeatedly holds an ageing token while the appliance mints fresh ones
13031
+ * nobody reads. Tokens are single-use with a 600s TTL, so that is the
13032
+ * reconnect case the feature is named for.
13033
+ */
13034
+ private reconnectTokenOption;
13035
+ /**
13036
+ * Throws when another login or a logout was issued after this one was sent,
13037
+ * so a stale answer cannot be reported to its caller as a successful login.
13038
+ */
13039
+ private assertNotSuperseded;
13040
+ /** Claim the next epoch for a login, and record it if a caller asked for it. */
13041
+ private beginLogin;
13042
+ private endLogin;
12900
13043
  loginWithUserPass(username: string, password: string): rxjs.Observable<AuthResponse>;
12901
13044
  loginWithOtp(code: string): rxjs.Observable<AuthResponse>;
13045
+ /**
13046
+ * Re-authenticate with a token from a previous login's `reconnect_token`.
13047
+ *
13048
+ * This is what lets a second connection to the same appliance authenticate
13049
+ * without asking the user for a password again — middleware sessions are
13050
+ * per-connection, so a second socket has its own to establish.
13051
+ *
13052
+ * The token is single-use and short-lived. On v26+ a successful login mints
13053
+ * another on the response, so a caller keeping a session alive across
13054
+ * reconnects stores the newest each time; below v26 nothing is minted and
13055
+ * there is no chain to keep.
13056
+ *
13057
+ * Re-login is the caller's to drive. A token session is not covered by the
13058
+ * automatic reconnect this class does for password and api-key sessions,
13059
+ * which is deliberate — the token is single-use — but it means a dropped
13060
+ * socket needs the stored token spending explicitly. Middleware holds tokens
13061
+ * in memory, so a `middlewared` restart voids them, and that is a common
13062
+ * reason the socket dropped in the first place.
13063
+ */
13064
+ loginWithToken(token: string): rxjs.Observable<AuthResponse>;
13065
+ /**
13066
+ * No reconnect token is requested here, though v26+ would mint one: an
13067
+ * api-key session already reconnects without a prompt, since the key is held
13068
+ * and replayed. The token exists for the credential that cannot be.
13069
+ */
12902
13070
  loginWithApiKey(credentials: {
12903
13071
  username: string;
12904
13072
  key: string;
@@ -12907,49 +13075,6 @@ declare class TrueNasAuthenticator {
12907
13075
  logout(): rxjs.Observable<boolean>;
12908
13076
  }
12909
13077
 
12910
- /**
12911
- * Response from the /api/versions endpoint
12912
- * Returns an array of version strings directly
12913
- * Example: ["v25.10.0", "v25.10.1", "v26.0.0"]
12914
- */
12915
- type ApiVersionResponse = string[];
12916
- /**
12917
- * Parsed API version information
12918
- *
12919
- * Version format:
12920
- * - Legacy (v25.x): vYY.MM.PATCH (e.g., v25.10.0 = October 2025, patch 0)
12921
- * - New (v26+): vYY.MINOR.PATCH (e.g., v26.0.0 = 2026, minor 0, patch 0)
12922
- *
12923
- * Note: The second segment has different semantics based on the year:
12924
- * - Year 25: month (1-12)
12925
- * - Year 26+: minor version (0-99)
12926
- */
12927
- interface ApiVersion {
12928
- /** Full version string (e.g., "v26.0.0") */
12929
- version: string;
12930
- /** Two-digit year (e.g., 26 = 2026) */
12931
- year: number;
12932
- /**
12933
- * Second version segment (semantics depend on year):
12934
- * - For v25.x: month (1-12, e.g., 10 = October)
12935
- * - For v26+: minor version (0-99)
12936
- */
12937
- minor: number;
12938
- /** Patch version number (e.g., 0, 1, 2) */
12939
- patch: number;
12940
- /** WebSocket path for this version (e.g., "/api/v26.0.0") */
12941
- websocketPath: string;
12942
- }
12943
- /**
12944
- * Version compatibility status
12945
- */
12946
- declare enum VersionCompatibility {
12947
- Compatible = "compatible",
12948
- TooOld = "too-old",
12949
- TooNew = "too-new",
12950
- Invalid = "invalid"
12951
- }
12952
-
12953
13078
  /**
12954
13079
  * The state `Container.status` is narrowed to.
12955
13080
  *
@@ -28043,6 +28168,19 @@ declare enum AuthErrorCode {
28043
28168
  PasswordAuthFailed = "PASSWORD_AUTH_FAILED",
28044
28169
  OtpAuthFailed = "OTP_AUTH_FAILED",
28045
28170
  ApiKeyAuthFailed = "API_KEY_AUTH_FAILED",
28171
+ TokenAuthFailed = "TOKEN_AUTH_FAILED",
28172
+ /**
28173
+ * A login was overtaken by a logout, or by a later login, while its response
28174
+ * was in flight. The server may well have accepted it; this client discarded
28175
+ * the result rather than authenticate a session the caller had moved on from.
28176
+ */
28177
+ LoginSuperseded = "LOGIN_SUPERSEDED",
28178
+ /**
28179
+ * @deprecated Nothing throws this. The authenticator no longer refuses a
28180
+ * login for want of a role — see `TrueNasAuthenticator`. Kept so consumers
28181
+ * still narrowing on the code keep compiling; removing it would be a breaking
28182
+ * change for a member that can no longer occur.
28183
+ */
28046
28184
  FullAdminRequired = "FULL_ADMIN_REQUIRED"
28047
28185
  }
28048
28186
  declare class AuthError extends Error {
@@ -28103,4 +28241,4 @@ type ApiError = JsonRpcError | TrueNasError;
28103
28241
  */
28104
28242
  declare function getApiErrorMessage(error: unknown, fallback?: string): string;
28105
28243
 
28106
- export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
28244
+ export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, UserRole, type UserRoleName, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
package/dist/index.d.ts CHANGED
@@ -12798,6 +12798,49 @@ declare class TrueNasApi<D extends ApiDirectoryShape = BaseApiDirectory> {
12798
12798
  private initializeJobEventsSubscription;
12799
12799
  }
12800
12800
 
12801
+ /**
12802
+ * Response from the /api/versions endpoint
12803
+ * Returns an array of version strings directly
12804
+ * Example: ["v25.10.0", "v25.10.1", "v26.0.0"]
12805
+ */
12806
+ type ApiVersionResponse = string[];
12807
+ /**
12808
+ * Parsed API version information
12809
+ *
12810
+ * Version format:
12811
+ * - Legacy (v25.x): vYY.MM.PATCH (e.g., v25.10.0 = October 2025, patch 0)
12812
+ * - New (v26+): vYY.MINOR.PATCH (e.g., v26.0.0 = 2026, minor 0, patch 0)
12813
+ *
12814
+ * Note: The second segment has different semantics based on the year:
12815
+ * - Year 25: month (1-12)
12816
+ * - Year 26+: minor version (0-99)
12817
+ */
12818
+ interface ApiVersion {
12819
+ /** Full version string (e.g., "v26.0.0") */
12820
+ version: string;
12821
+ /** Two-digit year (e.g., 26 = 2026) */
12822
+ year: number;
12823
+ /**
12824
+ * Second version segment (semantics depend on year):
12825
+ * - For v25.x: month (1-12, e.g., 10 = October)
12826
+ * - For v26+: minor version (0-99)
12827
+ */
12828
+ minor: number;
12829
+ /** Patch version number (e.g., 0, 1, 2) */
12830
+ patch: number;
12831
+ /** WebSocket path for this version (e.g., "/api/v26.0.0") */
12832
+ websocketPath: string;
12833
+ }
12834
+ /**
12835
+ * Version compatibility status
12836
+ */
12837
+ declare enum VersionCompatibility {
12838
+ Compatible = "compatible",
12839
+ TooOld = "too-old",
12840
+ TooNew = "too-new",
12841
+ Invalid = "invalid"
12842
+ }
12843
+
12801
12844
  interface ApiKeyCreate {
12802
12845
  id: number;
12803
12846
  key: string;
@@ -12808,6 +12851,20 @@ interface ApiKeyCreate {
12808
12851
  declare enum UserRole {
12809
12852
  FullAdmin = "FULL_ADMIN"
12810
12853
  }
12854
+ /**
12855
+ * A role as middleware reports it.
12856
+ *
12857
+ * `UserRole` names only the role this client itself had a use for. Middleware
12858
+ * defines many more — `SHARING_ADMIN`, `READONLY_ADMIN` and so on — and this
12859
+ * client does not enumerate them, because it no longer makes any decision from
12860
+ * a role and would only be maintaining a second copy of someone else's list.
12861
+ *
12862
+ * Widened to `string` so a consumer can compare against the roles it cares
12863
+ * about without a cast, while `UserRole` still autocompletes. Consumers are
12864
+ * where role policy lives now, so the type they are handed has to admit the
12865
+ * roles they will actually test for.
12866
+ */
12867
+ type UserRoleName = UserRole | (string & {});
12811
12868
 
12812
12869
  interface UserPreferences {
12813
12870
  language: string;
@@ -12824,6 +12881,24 @@ interface AuthResponse {
12824
12881
  response_type: AuthResponseType;
12825
12882
  username?: string;
12826
12883
  authenticator?: 'LEVEL_1' | 'LEVEL_2' | 'LEVEL_3';
12884
+ /**
12885
+ * A token for re-authenticating without credentials.
12886
+ *
12887
+ * Absent below v26: `AuthRespSuccess` there declares only `response_type`,
12888
+ * `user_info` and `authenticator`. From v26 it is always present and is
12889
+ * `null` when no token was minted — because none was asked for, or because
12890
+ * the session cannot have one. Middleware refuses for a session authenticated
12891
+ * by a one-time *password* (`auth.generate_onetime_password`), which is not
12892
+ * the same thing as 2FA despite this codebase spelling 2FA "OTP" throughout.
12893
+ *
12894
+ * A 2FA account gets `null` for a different reason, and it is this client's
12895
+ * doing rather than the server's: the password request carrying the option is
12896
+ * answered `OTP_REQUIRED` before anything is minted, and `loginWithOtp` does
12897
+ * not send `login_options` on the second step. Middleware would honour it
12898
+ * there — `auth.login_ex_continue` re-enters `login_ex`, and a 2FA session
12899
+ * may hold a token — so this is a gap to close, not a limit to work around.
12900
+ */
12901
+ reconnect_token?: string | null;
12827
12902
  max_session_age?: number;
12828
12903
  max_inactivity?: number;
12829
12904
  urls?: string[];
@@ -12835,7 +12910,7 @@ interface AuthResponse {
12835
12910
  groups: number[];
12836
12911
  privilege: {
12837
12912
  roles: {
12838
- $set: UserRole[];
12913
+ $set: UserRoleName[];
12839
12914
  };
12840
12915
  };
12841
12916
  two_factor_auth_configured: boolean;
@@ -12874,9 +12949,17 @@ interface AuthResponse {
12874
12949
  * TrueNAS authenticator using the JSON-RPC 2.0 protocol.
12875
12950
  *
12876
12951
  * It handles authentication using the JSON-RPC 2.0 message format.
12952
+ *
12953
+ * Authentication only: any credential middleware accepts logs in here, whatever
12954
+ * roles it carries. No path checks privilege, and that is the design — the
12955
+ * appliance authorizes every privileged call on its own, and which roles a given
12956
+ * product requires is that product's policy, not this client's. Consumers who
12957
+ * need one read `user_info.privilege.roles` off the response and enforce it
12958
+ * themselves; embedding a rule here would impose it on every consumer at once.
12877
12959
  */
12878
12960
  declare class TrueNasAuthenticator {
12879
12961
  private connection;
12962
+ private readonly version?;
12880
12963
  static readonly DefaultSessionLifetime = 300;
12881
12964
  /**
12882
12965
  * whether or not the system is currently authenticated and accessible.
@@ -12896,9 +12979,94 @@ declare class TrueNasAuthenticator {
12896
12979
  key: string;
12897
12980
  };
12898
12981
  sessionLifetime: number;
12899
- constructor(connection: TrueNasConnection);
12982
+ /**
12983
+ * Claimed by each login when it sends and checked when its answer lands: a
12984
+ * difference means another login or a logout was issued in between, so this
12985
+ * answer is stale and must not write session state. Responses on one socket
12986
+ * are not ordered, which is why arrival is not enough to make an answer
12987
+ * current.
12988
+ *
12989
+ * `logout()` bumps it without claiming one. It has no answer to guard —
12990
+ * it settles its own state at the call — and bumping is what invalidates the
12991
+ * logins already on the wire that a logout is meant to override.
12992
+ */
12993
+ private authEpoch;
12994
+ /**
12995
+ * Caller-issued logins still awaiting an answer, keyed by the epoch each
12996
+ * claimed. The value is whether its frame has been written to a socket yet.
12997
+ *
12998
+ * The auto-relogin below defers while any entry exists. It is this class
12999
+ * retrying a cached credential, not a request anyone made, so it must never
13000
+ * outrank an explicit login — and it would: `TrueNasConnection.send` holds a
13001
+ * frame through an outage rather than dropping it, so a login submitted while
13002
+ * the socket is down is still pending when `opened` fires, and a relogin
13003
+ * claiming the newer epoch has that login answered `LoginSuperseded` while the
13004
+ * client authenticates as the previously cached account.
13005
+ *
13006
+ * Keyed rather than counted, because a count cannot say *which* login a
13007
+ * removal belongs to: a login torn down by its caller would retire a slot
13008
+ * belonging to a different login that is still waiting, and the retry would
13009
+ * overtake it again. Identity also makes a double-subscribed login harmless.
13010
+ */
13011
+ private liveCallerLogins;
13012
+ /** True only while the constructor's relogin is being constructed. */
13013
+ private reloginInProgress;
13014
+ constructor(connection: TrueNasConnection, version?: ApiVersion | undefined);
13015
+ /**
13016
+ * `login_options` asking for a reconnect token, when the server understands it.
13017
+ *
13018
+ * Omitted below v26. `AuthCommonOptions` is `additionalProperties: false`
13019
+ * there and has only `user_info`, so sending the member is a validation
13020
+ * error, not an ignored field — it would fail login outright on the oldest
13021
+ * version this client supports.
13022
+ */
13023
+ /**
13024
+ * Two things this does not do, both deliberate and both worth knowing.
13025
+ *
13026
+ * There is no way for a consumer to decline: every v26+ password login now
13027
+ * mints a single-use credential carrying that session's roles, whether or not
13028
+ * the caller wants one. And the auto-relogin in the constructor subscribes
13029
+ * with no observer, so the token it mints is dropped — a caller reconnecting
13030
+ * repeatedly holds an ageing token while the appliance mints fresh ones
13031
+ * nobody reads. Tokens are single-use with a 600s TTL, so that is the
13032
+ * reconnect case the feature is named for.
13033
+ */
13034
+ private reconnectTokenOption;
13035
+ /**
13036
+ * Throws when another login or a logout was issued after this one was sent,
13037
+ * so a stale answer cannot be reported to its caller as a successful login.
13038
+ */
13039
+ private assertNotSuperseded;
13040
+ /** Claim the next epoch for a login, and record it if a caller asked for it. */
13041
+ private beginLogin;
13042
+ private endLogin;
12900
13043
  loginWithUserPass(username: string, password: string): rxjs.Observable<AuthResponse>;
12901
13044
  loginWithOtp(code: string): rxjs.Observable<AuthResponse>;
13045
+ /**
13046
+ * Re-authenticate with a token from a previous login's `reconnect_token`.
13047
+ *
13048
+ * This is what lets a second connection to the same appliance authenticate
13049
+ * without asking the user for a password again — middleware sessions are
13050
+ * per-connection, so a second socket has its own to establish.
13051
+ *
13052
+ * The token is single-use and short-lived. On v26+ a successful login mints
13053
+ * another on the response, so a caller keeping a session alive across
13054
+ * reconnects stores the newest each time; below v26 nothing is minted and
13055
+ * there is no chain to keep.
13056
+ *
13057
+ * Re-login is the caller's to drive. A token session is not covered by the
13058
+ * automatic reconnect this class does for password and api-key sessions,
13059
+ * which is deliberate — the token is single-use — but it means a dropped
13060
+ * socket needs the stored token spending explicitly. Middleware holds tokens
13061
+ * in memory, so a `middlewared` restart voids them, and that is a common
13062
+ * reason the socket dropped in the first place.
13063
+ */
13064
+ loginWithToken(token: string): rxjs.Observable<AuthResponse>;
13065
+ /**
13066
+ * No reconnect token is requested here, though v26+ would mint one: an
13067
+ * api-key session already reconnects without a prompt, since the key is held
13068
+ * and replayed. The token exists for the credential that cannot be.
13069
+ */
12902
13070
  loginWithApiKey(credentials: {
12903
13071
  username: string;
12904
13072
  key: string;
@@ -12907,49 +13075,6 @@ declare class TrueNasAuthenticator {
12907
13075
  logout(): rxjs.Observable<boolean>;
12908
13076
  }
12909
13077
 
12910
- /**
12911
- * Response from the /api/versions endpoint
12912
- * Returns an array of version strings directly
12913
- * Example: ["v25.10.0", "v25.10.1", "v26.0.0"]
12914
- */
12915
- type ApiVersionResponse = string[];
12916
- /**
12917
- * Parsed API version information
12918
- *
12919
- * Version format:
12920
- * - Legacy (v25.x): vYY.MM.PATCH (e.g., v25.10.0 = October 2025, patch 0)
12921
- * - New (v26+): vYY.MINOR.PATCH (e.g., v26.0.0 = 2026, minor 0, patch 0)
12922
- *
12923
- * Note: The second segment has different semantics based on the year:
12924
- * - Year 25: month (1-12)
12925
- * - Year 26+: minor version (0-99)
12926
- */
12927
- interface ApiVersion {
12928
- /** Full version string (e.g., "v26.0.0") */
12929
- version: string;
12930
- /** Two-digit year (e.g., 26 = 2026) */
12931
- year: number;
12932
- /**
12933
- * Second version segment (semantics depend on year):
12934
- * - For v25.x: month (1-12, e.g., 10 = October)
12935
- * - For v26+: minor version (0-99)
12936
- */
12937
- minor: number;
12938
- /** Patch version number (e.g., 0, 1, 2) */
12939
- patch: number;
12940
- /** WebSocket path for this version (e.g., "/api/v26.0.0") */
12941
- websocketPath: string;
12942
- }
12943
- /**
12944
- * Version compatibility status
12945
- */
12946
- declare enum VersionCompatibility {
12947
- Compatible = "compatible",
12948
- TooOld = "too-old",
12949
- TooNew = "too-new",
12950
- Invalid = "invalid"
12951
- }
12952
-
12953
13078
  /**
12954
13079
  * The state `Container.status` is narrowed to.
12955
13080
  *
@@ -28043,6 +28168,19 @@ declare enum AuthErrorCode {
28043
28168
  PasswordAuthFailed = "PASSWORD_AUTH_FAILED",
28044
28169
  OtpAuthFailed = "OTP_AUTH_FAILED",
28045
28170
  ApiKeyAuthFailed = "API_KEY_AUTH_FAILED",
28171
+ TokenAuthFailed = "TOKEN_AUTH_FAILED",
28172
+ /**
28173
+ * A login was overtaken by a logout, or by a later login, while its response
28174
+ * was in flight. The server may well have accepted it; this client discarded
28175
+ * the result rather than authenticate a session the caller had moved on from.
28176
+ */
28177
+ LoginSuperseded = "LOGIN_SUPERSEDED",
28178
+ /**
28179
+ * @deprecated Nothing throws this. The authenticator no longer refuses a
28180
+ * login for want of a role — see `TrueNasAuthenticator`. Kept so consumers
28181
+ * still narrowing on the code keep compiling; removing it would be a breaking
28182
+ * change for a member that can no longer occur.
28183
+ */
28046
28184
  FullAdminRequired = "FULL_ADMIN_REQUIRED"
28047
28185
  }
28048
28186
  declare class AuthError extends Error {
@@ -28103,4 +28241,4 @@ type ApiError = JsonRpcError | TrueNasError;
28103
28241
  */
28104
28242
  declare function getApiErrorMessage(error: unknown, fallback?: string): string;
28105
28243
 
28106
- export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };
28244
+ export { type ApiCallDirectory$7 as ApiCallDirectoryV25_10_0, type ApiCallDirectory$6 as ApiCallDirectoryV25_10_1, type ApiCallDirectory$5 as ApiCallDirectoryV25_10_2, type ApiCallDirectory$4 as ApiCallDirectoryV25_10_3, type ApiCallDirectory$3 as ApiCallDirectoryV25_10_4, type ApiCallDirectory$2 as ApiCallDirectoryV25_10_5, type ApiCallDirectory$1 as ApiCallDirectoryV26_0_0, type ApiCallDirectory as ApiCallDirectoryV27_0_0, type ApiDirectoryByVersion, type ApiDirectoryShape, type ApiDirectory$7 as ApiDirectoryV25_10_0, type ApiDirectory$6 as ApiDirectoryV25_10_1, type ApiDirectory$5 as ApiDirectoryV25_10_2, type ApiDirectory$4 as ApiDirectoryV25_10_3, type ApiDirectory$3 as ApiDirectoryV25_10_4, type ApiDirectory$2 as ApiDirectoryV25_10_5, type ApiDirectory$1 as ApiDirectoryV26_0_0, type ApiDirectory as ApiDirectoryV27_0_0, type ApiError, type ApiEventDirectory$7 as ApiEventDirectoryV25_10_0, type ApiEventDirectory$6 as ApiEventDirectoryV25_10_1, type ApiEventDirectory$5 as ApiEventDirectoryV25_10_2, type ApiEventDirectory$4 as ApiEventDirectoryV25_10_3, type ApiEventDirectory$3 as ApiEventDirectoryV25_10_4, type ApiEventDirectory$2 as ApiEventDirectoryV25_10_5, type ApiEventDirectory$1 as ApiEventDirectoryV26_0_0, type ApiEventDirectory as ApiEventDirectoryV27_0_0, type ApiJobDirectory$7 as ApiJobDirectoryV25_10_0, type ApiJobDirectory$6 as ApiJobDirectoryV25_10_1, type ApiJobDirectory$5 as ApiJobDirectoryV25_10_2, type ApiJobDirectory$4 as ApiJobDirectoryV25_10_3, type ApiJobDirectory$3 as ApiJobDirectoryV25_10_4, type ApiJobDirectory$2 as ApiJobDirectoryV25_10_5, type ApiJobDirectory$1 as ApiJobDirectoryV26_0_0, type ApiJobDirectory as ApiJobDirectoryV27_0_0, type ApiKeyCreate, type ApiVersion, type ApiVersionResponse, AppState, type ApplianceProtocol, type ArgsOf, AuthError, AuthErrorCode, type AuthResponse, type BaseApiDirectory, type CallMethod, type CallParams, type CallResponse, type Container, type CreateClientOptions, type DefaultApiDirectory, type EventKind, type EventName, type EventUnion, InvalidVersionResponseError, type Job, type JobMethod, type JobParams, type JobProgress, type JobResult, JobState, type Logger, NoCompatibleVersionsError, type OperationMappings, type QueryDirectory, type QueryEntity, type QueryListOptions, type QueryMethod, type QuerySingleOptions, SUPPORTED_API_VERSIONS, type SupportedApiVersion, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV26, TrueNasApiClientV27, TrueNasAuthMechanism, type TrueNasDate, UserRole, type UserRoleName, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, consoleLogger, createTrueNasClient, getApiErrorMessage, isJobFinished, noopLogger, index$7 as v25_10_0, index$6 as v25_10_1, index$5 as v25_10_2, index$4 as v25_10_3, index$3 as v25_10_4, index$2 as v25_10_5, index$1 as v26_0_0, index as v27_0_0 };