@qodalis/cli-core 2.0.0-beta.13 → 2.0.0-beta.14

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/public-api.d.mts CHANGED
@@ -637,6 +637,32 @@ declare const ICliFilePickerProvider_TOKEN = "cli-file-picker-provider";
637
637
  * Token for the HTTP client service.
638
638
  */
639
639
  declare const ICliHttpClient_TOKEN = "cli-http-client";
640
+ /**
641
+ * Token for the user event service (lifecycle events).
642
+ */
643
+ declare const ICliUserEventService_TOKEN = "cli-user-event-service";
644
+ /**
645
+ * Token for the audit service (persistent event logging).
646
+ */
647
+ declare const ICliAuditService_TOKEN = "cli-audit-service";
648
+ /**
649
+ * Token for the authorization service ({@link ICliAuthorizationService}).
650
+ * Provided by an auth module (e.g. `@qodalis/cli-users`); absent otherwise.
651
+ */
652
+ declare const ICliAuthorizationService_TOKEN = "cli-authorization-service";
653
+ /**
654
+ * Token for the permission registry ({@link ICliPermissionRegistry}).
655
+ * Always provided by the CLI engine.
656
+ */
657
+ declare const ICliPermissionRegistry_TOKEN = "cli-permission-registry";
658
+ /**
659
+ * Token for the sessions service ({@link ICliSessionsService}).
660
+ */
661
+ declare const ICliSessionsService_TOKEN = "cli-sessions-service";
662
+ /**
663
+ * Token for the persistent key-value store used by modules (setup state, etc.).
664
+ */
665
+ declare const ICliKeyValueStore_TOKEN = "cli-key-value-store";
640
666
 
641
667
  /**
642
668
  * Abstract permission service for checking rwx permissions on resources.
@@ -990,6 +1016,235 @@ interface ICliTextAnimator extends ICliProgressBar {
990
1016
  showText: (text: string, options?: CliTextAnimatorOptions) => Promise<void>;
991
1017
  }
992
1018
 
1019
+ /**
1020
+ * Result of a guard check.
1021
+ *
1022
+ * - `true` or `undefined`: allow the command.
1023
+ * - `false`: block it with the generic message `<command>: permission denied`.
1024
+ * - a non-empty `string`: block it and print this message.
1025
+ * - `{ allowed, message }`: explicit form; `message` is used when `allowed` is false.
1026
+ */
1027
+ type CliCommandGuardResult = boolean | string | void | {
1028
+ allowed: boolean;
1029
+ message?: string;
1030
+ };
1031
+ /**
1032
+ * A global command guard: a check that runs before **every** command, across
1033
+ * all processors and modules, and can block it.
1034
+ *
1035
+ * Use guards for cross-cutting policies such as authentication, permission
1036
+ * checks, feature flags, maintenance windows or rate limiting, instead of
1037
+ * repeating the check inside each processor.
1038
+ *
1039
+ * ## When guards run
1040
+ *
1041
+ * For each command the executor:
1042
+ * 1. parses the input and resolves the processor (and sub-processor);
1043
+ * 2. handles global parameters such as `--help` (help is never guarded);
1044
+ * 3. extracts the positional value into `command.value`;
1045
+ * 4. **runs the guards**;
1046
+ * 5. validates required values/parameters, runs processor hooks and finally
1047
+ * calls `processCommand`.
1048
+ *
1049
+ * Guards run in ascending `priority` (default `0`). For each guard the executor
1050
+ * calls `appliesTo` (if defined) and skips the guard when it returns `false`;
1051
+ * otherwise it awaits `canActivate`. The **first** guard that blocks stops the
1052
+ * chain: its message is written as an error and the command exits with code
1053
+ * `-1`. A guard that throws (in `appliesTo` or `canActivate`) also blocks the
1054
+ * command, so a broken guard fails closed.
1055
+ *
1056
+ * ## Access to the context
1057
+ *
1058
+ * Both `appliesTo` and `canActivate` receive the {@link ICliExecutionContext}
1059
+ * of the command about to run, so a guard can:
1060
+ * - resolve services with `context.services.get(...)` / `getRequired(...)`
1061
+ * (e.g. a policy, feature-flag or permission service registered by any
1062
+ * module) to decide **what** should be guarded and **whether** it may run;
1063
+ * - inspect `context.userSession` for the signed-in user and their groups;
1064
+ * - read the processor's `metadata` (for example `requireAuth` or
1065
+ * `requiredGroups`) and the parsed `command` (`command.value`, `command.args`);
1066
+ * - prompt the user via `context.reader` (e.g. a confirmation guard).
1067
+ *
1068
+ * Guards should not write to the terminal to report a denial; return a message
1069
+ * instead so the executor prints it consistently.
1070
+ *
1071
+ * ## Registering guards
1072
+ *
1073
+ * The preferred way is the module's `guards` array; the boot sequence
1074
+ * registers each entry as a multi-provider under {@link ICliCommandGuard_TOKEN}.
1075
+ * Several modules can contribute guards; all of them run.
1076
+ *
1077
+ * ```ts
1078
+ * const billingModule: ICliModule = {
1079
+ * apiVersion: 2,
1080
+ * name: 'billing',
1081
+ * processors: [new InvoiceProcessor()],
1082
+ * guards: [billingGuard],
1083
+ * };
1084
+ * ```
1085
+ *
1086
+ * Guards can also be added at runtime (e.g. from `onInit`):
1087
+ *
1088
+ * ```ts
1089
+ * context.services.set({ provide: ICliCommandGuard_TOKEN, useValue: myGuard, multi: true });
1090
+ * ```
1091
+ *
1092
+ * ## Example: policy resolved from a service
1093
+ *
1094
+ * ```ts
1095
+ * const featureFlagGuard: ICliCommandGuard = {
1096
+ * name: 'feature-flags',
1097
+ * // Only guard commands that are behind a flag; the flag list comes from a service
1098
+ * appliesTo: (processor, _command, context) =>
1099
+ * context.services.get<FeatureFlags>(FeatureFlags_TOKEN)?.isFlagged(processor.command) ?? false,
1100
+ * canActivate: async (_command, processor, context) => {
1101
+ * const flags = context.services.getRequired<FeatureFlags>(FeatureFlags_TOKEN);
1102
+ * return (await flags.isEnabled(processor.command, context.userSession?.user))
1103
+ * ? true
1104
+ * : `${processor.command}: not available for your account`;
1105
+ * },
1106
+ * };
1107
+ * ```
1108
+ *
1109
+ * ## Without a guard-providing module
1110
+ *
1111
+ * Guards are opt-in. When no guard is registered every command runs as before.
1112
+ * The engine registers three built-in guards that enforce the processor access
1113
+ * metadata (`requireAuth`, `requiredGroups`, `requiredPermissions`); they stay
1114
+ * inactive until an auth module (e.g. `@qodalis/cli-users`) registers an
1115
+ * `ICliAuthorizationService`, so without one that metadata is informational.
1116
+ */
1117
+ interface ICliCommandGuard {
1118
+ /** Unique name, shown in diagnostics when the guard throws. */
1119
+ name: string;
1120
+ /** Execution order; lower runs first. Defaults to `0`. */
1121
+ priority?: number;
1122
+ /**
1123
+ * Optional filter deciding whether this guard is relevant for the command.
1124
+ * Return `false` to skip the guard. When omitted the guard applies to
1125
+ * every command. May be async, and may use `context` to resolve services.
1126
+ */
1127
+ appliesTo?(processor: ICliCommandProcessor, command: CliProcessCommand, context: ICliExecutionContext): boolean | Promise<boolean>;
1128
+ /**
1129
+ * Decide whether the command may run. See {@link CliCommandGuardResult}
1130
+ * for the accepted return values.
1131
+ */
1132
+ canActivate(command: CliProcessCommand, processor: ICliCommandProcessor, context: ICliExecutionContext): CliCommandGuardResult | Promise<CliCommandGuardResult>;
1133
+ }
1134
+ /** DI token for {@link ICliCommandGuard}; register guards as multi-providers. */
1135
+ declare const ICliCommandGuard_TOKEN = "cli-command-guard";
1136
+
1137
+ /**
1138
+ * A permission an extension uses, declared so tools (`perms --list`,
1139
+ * `groupmod --grant` completion, docs) can show it. Declaring is optional:
1140
+ * any `resource:action` string can be granted and checked.
1141
+ */
1142
+ interface CliPermissionDefinition {
1143
+ /** Permission string, `resource:action` (e.g. `files:chown`). */
1144
+ name: string;
1145
+ /** Human readable description. */
1146
+ description?: string;
1147
+ /** Module that declared it (filled in at registration). */
1148
+ module?: string;
1149
+ }
1150
+ /** Registry of permissions declared by modules (`ICliModule.permissions`). */
1151
+ interface ICliPermissionRegistry {
1152
+ register(definitions: CliPermissionDefinition[], module?: string): void;
1153
+ list(): CliPermissionDefinition[];
1154
+ get(name: string): CliPermissionDefinition | undefined;
1155
+ }
1156
+ /** The identity checks are made against. */
1157
+ interface ICliPrincipal {
1158
+ /** User id */
1159
+ id: string;
1160
+ /** Login name (used as file owner) */
1161
+ name: string;
1162
+ /** Group (role) names */
1163
+ groups: string[];
1164
+ /** Effective permissions (union of the groups' permissions) */
1165
+ permissions: string[];
1166
+ }
1167
+ /** rwx-style protected resource (files, directories, or anything an extension owns). */
1168
+ interface ICliProtectedResource {
1169
+ ownership?: ICliOwnership;
1170
+ /** 9-char mode string, e.g. `rwxr-x---` */
1171
+ permissions?: string;
1172
+ }
1173
+ type CliAccessAction = 'read' | 'write' | 'execute';
1174
+ /**
1175
+ * Authorization service. Provided by an auth module (the users module provides
1176
+ * one in local and in server mode). Extensions should use the helpers
1177
+ * {@link cliAuthorize} / {@link cliCanAccess}, which allow everything when no
1178
+ * authorization service is registered.
1179
+ */
1180
+ interface ICliAuthorizationService {
1181
+ /** The signed-in principal, or undefined when nobody is signed in. */
1182
+ getPrincipal(): ICliPrincipal | undefined;
1183
+ /** Does the current principal hold `permission` (wildcards honoured)? */
1184
+ can(permission: string): boolean;
1185
+ /**
1186
+ * rwx check on a resource for the current principal (owner / group / other).
1187
+ * Principals holding `*` or any of `bypassPermissions` are always allowed.
1188
+ * Resources without a mode or ownership are allowed.
1189
+ */
1190
+ canAccess(resource: ICliProtectedResource, action: CliAccessAction, bypassPermissions?: string[]): boolean;
1191
+ }
1192
+ /** Thrown when an operation is not permitted. The message is user facing. */
1193
+ declare class CliAccessDeniedError extends Error {
1194
+ readonly code = "EACCES";
1195
+ constructor(message?: string);
1196
+ }
1197
+ /** True for {@link CliAccessDeniedError} (also across bundle copies). */
1198
+ declare function isCliAccessDeniedError(error: unknown): error is CliAccessDeniedError;
1199
+ /**
1200
+ * Check a permission for the current principal. Returns `true` when no
1201
+ * authorization service is registered (no auth module loaded).
1202
+ */
1203
+ declare function cliAuthorize(context: Pick<ICliExecutionContext, 'services'>, permission: string): boolean;
1204
+ /**
1205
+ * rwx check for the current principal. Returns `true` when no authorization
1206
+ * service is registered.
1207
+ */
1208
+ declare function cliCanAccess(context: Pick<ICliExecutionContext, 'services'>, resource: ICliProtectedResource, action: CliAccessAction, bypassPermissions?: string[]): boolean;
1209
+ /**
1210
+ * Reference rwx evaluation shared by implementations of
1211
+ * {@link ICliAuthorizationService.canAccess}.
1212
+ */
1213
+ declare function cliEvaluateAccess(principal: ICliPrincipal | undefined, resource: ICliProtectedResource, action: CliAccessAction, bypassPermissions?: string[]): boolean;
1214
+
1215
+ /** A sign-in session as listed by {@link ICliSessionsService}. Never carries a token. */
1216
+ interface ICliSessionInfo {
1217
+ id: string;
1218
+ userId: string;
1219
+ userName: string;
1220
+ createdAt: number;
1221
+ lastActivity: number;
1222
+ /** When the session expires if idle; undefined when there is no timeout */
1223
+ expiresAt?: number;
1224
+ /** True for the caller's own session */
1225
+ current?: boolean;
1226
+ metadata?: {
1227
+ userAgent?: string;
1228
+ remoteAddress?: string;
1229
+ [key: string]: unknown;
1230
+ };
1231
+ }
1232
+ /**
1233
+ * Lists and revokes sign-in sessions. Implemented locally (sessions of this
1234
+ * browser) and by servers (all sessions). Used by `sessions` / `session-kick`.
1235
+ */
1236
+ interface ICliSessionsService {
1237
+ /** All sessions visible to the caller */
1238
+ list(): Promise<ICliSessionInfo[]>;
1239
+ /** Revoke a session by id */
1240
+ revoke(sessionId: string, reason?: string): Promise<void>;
1241
+ /** Revoke every session of a user (optionally keeping one) */
1242
+ revokeUser(userId: string, options?: {
1243
+ exceptSessionId?: string;
1244
+ reason?: string;
1245
+ }): Promise<void>;
1246
+ }
1247
+
993
1248
  /**
994
1249
  * Represents a service that manages user sessions in the CLI
995
1250
  */
@@ -1032,8 +1287,17 @@ interface ICliGroupsStoreService {
1032
1287
  getGroups(): Observable<ICliGroup[]>;
1033
1288
  /** Gets a group by id or name */
1034
1289
  getGroup(id: string): Observable<ICliGroup | undefined>;
1035
- /** Creates a new group */
1036
- createGroup(name: string, description?: string): Promise<ICliGroup>;
1290
+ /** Creates a new group (role), optionally with permissions */
1291
+ createGroup(name: string, description?: string, permissions?: string[]): Promise<ICliGroup>;
1292
+ /** Updates a group's description and/or permissions (by id or name) */
1293
+ updateGroup(id: string, updates: {
1294
+ description?: string;
1295
+ permissions?: string[];
1296
+ }): Promise<ICliGroup>;
1297
+ /** Adds a user (id or name) to a group (id or name) */
1298
+ addMember(groupId: string, userId: string): Promise<void>;
1299
+ /** Removes a user (id or name) from a group (id or name) */
1300
+ removeMember(groupId: string, userId: string): Promise<void>;
1037
1301
  /** Deletes a group by id */
1038
1302
  deleteGroup(id: string): Promise<void>;
1039
1303
  /** Gets all users that belong to a group */
@@ -1043,16 +1307,32 @@ interface ICliGroupsStoreService {
1043
1307
  * Represents a service that handles authentication in the CLI
1044
1308
  */
1045
1309
  interface ICliAuthService {
1046
- /** Authenticates a user and returns a session */
1047
- login(username: string, password: string): Promise<ICliUserSession>;
1048
- /** Ends the current session */
1310
+ /**
1311
+ * Authenticates a user and returns a session. `password` may be omitted
1312
+ * only when the implementation allows passwordless sign-in.
1313
+ */
1314
+ login(username: string, password?: string): Promise<ICliUserSession>;
1315
+ /** Ends the current session (the CLI is left signed out) */
1049
1316
  logout(): Promise<void>;
1050
- /** Sets or updates a user's password */
1051
- setPassword(userId: string, password: string): Promise<void>;
1317
+ /**
1318
+ * Switch to another user (`su`). Requires the target's password unless
1319
+ * the caller may skip it (implementation-defined, e.g. `users:update`).
1320
+ * Goes through the same lockout, events and audit as `login`.
1321
+ */
1322
+ switchUser?(username: string, password?: string): Promise<ICliUserSession>;
1323
+ /**
1324
+ * Sets or updates a user's password.
1325
+ * @param currentPassword The user's current password, when changing one's own
1326
+ * password. Server-backed implementations forward it so the server can
1327
+ * re-check it; local implementations may ignore it.
1328
+ */
1329
+ setPassword(userId: string, password: string, currentPassword?: string): Promise<void>;
1052
1330
  /** Verifies a password against stored credentials */
1053
1331
  verifyPassword(userId: string, password: string): Promise<boolean>;
1054
1332
  /** Hashes a password with a salt using Web Crypto SHA-256 */
1055
1333
  hashPassword(password: string, salt: string): Promise<string>;
1334
+ /** Validate password against policy. Returns error message or null if valid. */
1335
+ validatePassword?(password: string): string | null;
1056
1336
  }
1057
1337
 
1058
1338
  /**
@@ -1434,6 +1714,24 @@ type CliProcessorMetadata = Record<string, any> & {
1434
1714
  * If the installed CLI version is lower, the processor will be skipped during boot.
1435
1715
  */
1436
1716
  requiredCliVersion?: string;
1717
+ /**
1718
+ * If true, the command requires a signed-in user. Enforced by a
1719
+ * core guard that activates when an auth module registers an
1720
+ * `ICliAuthorizationService` (e.g. `@qodalis/cli-users`); without one the
1721
+ * flag is informational.
1722
+ */
1723
+ requireAuth?: boolean;
1724
+ /**
1725
+ * The signed-in user must belong to at least one of these groups
1726
+ * (e.g. `['admin']`). Implies `requireAuth`. Enforced like `requireAuth`.
1727
+ */
1728
+ requiredGroups?: string[];
1729
+ /**
1730
+ * The signed-in user must hold **all** of these permissions
1731
+ * (e.g. `['users:create']`), granted through their groups (roles).
1732
+ * Implies `requireAuth`. Enforced like `requireAuth`.
1733
+ */
1734
+ requiredPermissions?: string[];
1437
1735
  /**
1438
1736
  * If true, the processor is hidden from the help command listing.
1439
1737
  * The command still works when typed directly and `help <command>` still shows its details.
@@ -1670,6 +1968,39 @@ interface ICliHttpClient {
1670
1968
  */
1671
1969
  options<T = any>(url: string, options?: CliHttpRequestOptions): Promise<T>;
1672
1970
  }
1971
+ /**
1972
+ * Error thrown by `ICliHttpClient` JSON helpers (`get`, `post`, `put`,
1973
+ * `patch`, `delete`, `options`) when the server responds with a non-2xx status.
1974
+ *
1975
+ * Exposes the HTTP status so callers can react to specific responses
1976
+ * (for example, clearing a stored session token on `401`).
1977
+ *
1978
+ * @example
1979
+ * ```ts
1980
+ * try {
1981
+ * await context.http.get(url);
1982
+ * } catch (e) {
1983
+ * if (e instanceof CliHttpError && e.status === 401) {
1984
+ * // token expired or revoked
1985
+ * }
1986
+ * }
1987
+ * ```
1988
+ */
1989
+ declare class CliHttpError extends Error {
1990
+ /** HTTP status code of the failed response */
1991
+ readonly status: number;
1992
+ /** HTTP status text of the failed response */
1993
+ readonly statusText: string;
1994
+ /** Parsed JSON error body, when the server returned one */
1995
+ readonly body?: unknown | undefined;
1996
+ constructor(message: string,
1997
+ /** HTTP status code of the failed response */
1998
+ status: number,
1999
+ /** HTTP status text of the failed response */
2000
+ statusText?: string,
2001
+ /** Parsed JSON error body, when the server returned one */
2002
+ body?: unknown | undefined);
2003
+ }
1673
2004
 
1674
2005
  type CliNotificationLevel = 'info' | 'success' | 'warn' | 'error';
1675
2006
  interface CliNotification {
@@ -1695,6 +2026,64 @@ interface ICliNotifier {
1695
2026
  readonly change$: Observable<CliNotification | undefined>;
1696
2027
  }
1697
2028
 
2029
+ /** Represents a user lifecycle event */
2030
+ interface ICliUserEvent {
2031
+ /** The type of event that occurred */
2032
+ type: 'login' | 'logout' | 'login_failed' | 'user_created' | 'user_deleted' | 'user_updated' | 'password_changed' | 'user_switched' | 'user_disabled' | 'user_enabled' | 'group_created' | 'group_updated' | 'group_deleted' | 'group_member_added' | 'group_member_removed' | 'session_revoked' | 'audit_cleared';
2033
+ /** The user involved in the event (for group events: the acting user) */
2034
+ user: ICliUser;
2035
+ /** The acting user's name, when different from `user` (e.g. an admin) */
2036
+ actor?: string;
2037
+ /** When the event occurred */
2038
+ timestamp: number;
2039
+ /** Optional additional details */
2040
+ details?: string;
2041
+ /** `user_updated`: the user's name before a rename (set only when the name changed) */
2042
+ previousName?: string;
2043
+ }
2044
+ /** Service that emits user lifecycle events for plugins to subscribe to */
2045
+ interface ICliUserEventService {
2046
+ /** Observable stream of user events */
2047
+ readonly events$: Observable<ICliUserEvent>;
2048
+ /** Emit a user event */
2049
+ emit(event: ICliUserEvent): void;
2050
+ }
2051
+
2052
+ /** A single audit log entry */
2053
+ interface ICliAuditEntry {
2054
+ /** Entry id (server-assigned in server mode) */
2055
+ id?: string;
2056
+ /** When the event occurred */
2057
+ timestamp: number;
2058
+ /** Event type (e.g., 'login', 'logout', 'login_failed') */
2059
+ event: string;
2060
+ /** Username involved */
2061
+ username: string;
2062
+ /** Optional additional details */
2063
+ details?: string;
2064
+ /** Id of the user the entry is about, when known */
2065
+ userId?: string;
2066
+ /** The user who performed the action, when different from `username` */
2067
+ actor?: string;
2068
+ /** Id of the acting user, when different from the subject */
2069
+ actorId?: string;
2070
+ /** Extra data (e.g. remote address) */
2071
+ metadata?: Record<string, unknown>;
2072
+ }
2073
+ /** Service for persistent audit logging */
2074
+ interface ICliAuditService {
2075
+ /** Log an audit entry (timestamp is added automatically) */
2076
+ log(entry: Omit<ICliAuditEntry, 'timestamp'>): Promise<void>;
2077
+ /** Retrieve audit entries with optional filtering */
2078
+ getEntries(options?: {
2079
+ limit?: number;
2080
+ event?: string;
2081
+ username?: string;
2082
+ }): Promise<ICliAuditEntry[]>;
2083
+ /** Clear all audit entries */
2084
+ clear(): Promise<void>;
2085
+ }
2086
+
1698
2087
  /**
1699
2088
  * A managed timer handle returned by createInterval/createTimeout.
1700
2089
  * Managed timers are automatically cleared when full-screen mode exits
@@ -2227,6 +2616,17 @@ interface ICliModule {
2227
2616
  processors?: ICliCommandProcessor[];
2228
2617
  /** Services registered into the shared service container */
2229
2618
  services?: CliProvider[];
2619
+ /**
2620
+ * Global command guards contributed by this module. They are registered
2621
+ * when the module boots and run before every command (across all modules),
2622
+ * e.g. authentication or permission checks. See {@link ICliCommandGuard}.
2623
+ */
2624
+ guards?: ICliCommandGuard[];
2625
+ /**
2626
+ * Permissions this module uses (`resource:action`), registered in the
2627
+ * {@link ICliPermissionRegistry} at boot so they can be listed and granted.
2628
+ */
2629
+ permissions?: CliPermissionDefinition[];
2230
2630
  /** Module configuration, set via configure() */
2231
2631
  config?: Record<string, any>;
2232
2632
  /**
@@ -2435,7 +2835,35 @@ interface ICliServerAuthTokenProvider {
2435
2835
  * @returns Headers to merge into the request, or an empty object
2436
2836
  */
2437
2837
  getHeaders(serverName: string): Record<string, string>;
2838
+ /**
2839
+ * Optional: query parameters for WebSocket upgrades to this server (e.g. a
2840
+ * short-lived single-use ticket). Called right before each connection.
2841
+ * Return `undefined` when this provider does not handle the server.
2842
+ * When any provider returns params, headers are NOT copied into the URL
2843
+ * (so bearer tokens never appear in WebSocket URLs).
2844
+ */
2845
+ getWebSocketParams?(serverName: string): Promise<Record<string, string> | undefined>;
2846
+ }
2847
+ /**
2848
+ * Minimal view of the CLI server manager (token `ICliServerManager_TOKEN`),
2849
+ * e.g. for auth modules that must refresh a server after sign-in.
2850
+ */
2851
+ interface ICliServerManager {
2852
+ /** Reconnect a server: re-fetch its commands and reopen its event socket. */
2853
+ reconnect(name: string): Promise<{
2854
+ success: boolean;
2855
+ commandCount: number;
2856
+ }>;
2857
+ /**
2858
+ * The server a command should target when the user names none: the
2859
+ * default server (`server default`) when connected, otherwise the first
2860
+ * connected server. `null` when no server is connected (for example every
2861
+ * server requires a login the user has not done yet).
2862
+ */
2863
+ preferredServer?(): string | null;
2438
2864
  }
2865
+ /** Token for {@link ICliServerManager} */
2866
+ declare const ICliServerManager_TOKEN = "cli-server-manager";
2439
2867
  /**
2440
2868
  * Internal service that resolves auth headers for a server by merging:
2441
2869
  * 1. Static/dynamic headers from `CliServerConfig.headers`
@@ -2453,6 +2881,11 @@ interface ICliServerAuthService {
2453
2881
  * @returns Merged headers ready for use in fetch/WebSocket calls
2454
2882
  */
2455
2883
  getHeaders(serverName: string, configHeaders?: CliHeadersProvider): Record<string, string>;
2884
+ /**
2885
+ * WebSocket upgrade query params from the registered token providers, or
2886
+ * `undefined` when no provider handles this server.
2887
+ */
2888
+ getWebSocketParams?(serverName: string): Promise<Record<string, string> | undefined>;
2456
2889
  }
2457
2890
 
2458
2891
  /**
@@ -2616,6 +3049,12 @@ interface ICliUser {
2616
3049
  updatedAt: number;
2617
3050
  /** Whether the account is locked */
2618
3051
  disabled?: boolean;
3052
+ /** The user must set a new password before doing anything else */
3053
+ mustChangePassword?: boolean;
3054
+ /** Extensible metadata (department, phone, preferences, etc.) */
3055
+ data?: Record<string, any>;
3056
+ /** Timestamp of last successful login */
3057
+ lastLoginAt?: number;
2619
3058
  }
2620
3059
  /**
2621
3060
  * Represents user credentials (shadow pattern — stored separately from ICliUser)
@@ -2642,6 +3081,16 @@ interface ICliGroup {
2642
3081
  description?: string;
2643
3082
  /** Group creation timestamp */
2644
3083
  createdAt: number;
3084
+ /**
3085
+ * Permissions granted to every member of the group. Groups act as roles.
3086
+ * Permission strings are `resource:action` (e.g. `users:create`), with
3087
+ * `*` wildcards (`users:*`, `*`). See {@link cliPermissionMatches}.
3088
+ */
3089
+ permissions?: string[];
3090
+ /** Built-in groups (`admin`, `users`) cannot be deleted */
3091
+ builtIn?: boolean;
3092
+ /** Last modification timestamp */
3093
+ updatedAt?: number;
2645
3094
  }
2646
3095
  /**
2647
3096
  * Represents an active user session
@@ -2655,6 +3104,11 @@ interface ICliUserSession {
2655
3104
  loginTime: number;
2656
3105
  /** Timestamp of last activity */
2657
3106
  lastActivity: number;
3107
+ /**
3108
+ * Effective permissions of the user (union of their groups' permissions),
3109
+ * resolved by the users module at login and refreshed when groups change.
3110
+ */
3111
+ permissions?: string[];
2658
3112
  /** Extensible data (tokens, metadata, etc.) */
2659
3113
  data?: Record<string, any>;
2660
3114
  }
@@ -2861,6 +3315,15 @@ declare class ServerVersionNegotiator {
2861
3315
  * @returns The WebSocket URL with auth credentials appended as query parameters
2862
3316
  */
2863
3317
  declare function buildAuthenticatedWebSocketUrl(wsUrl: string, headers?: CliHeadersProvider): string;
3318
+ /**
3319
+ * Build the WebSocket URL for a configured server. Prefers upgrade params
3320
+ * from auth providers (e.g. a single-use ticket from the users module); only
3321
+ * when no provider handles the server are headers copied into the URL
3322
+ * (legacy behaviour, see {@link buildAuthenticatedWebSocketUrl}).
3323
+ */
3324
+ declare function resolveServerWebSocketUrl(services: ICliServiceProvider | undefined, serverName: string, wsUrl: string, configHeaders?: CliHeadersProvider): Promise<string>;
3325
+ /** Append query params to a URL that may already have some. */
3326
+ declare function appendQueryParams(url: string, params: Record<string, string>): string;
2864
3327
 
2865
3328
  /**
2866
3329
  * Derives CLI panel CSS custom property values from an xterm ITheme object.
@@ -2910,6 +3373,85 @@ declare function stripAnsi(text: string): string;
2910
3373
  */
2911
3374
  declare function visibleLength(text: string): number;
2912
3375
 
3376
+ /**
3377
+ * Permission strings are `resource:action` (for example `users:create`).
3378
+ * A trailing `*` segment matches anything at that level and below; a `*`
3379
+ * in any other position matches exactly one segment:
3380
+ *
3381
+ * | granted | matches |
3382
+ * |---------------|---------------------------------------|
3383
+ * | `*` | every permission |
3384
+ * | `users:*` | `users:create`, `users:delete`, ... |
3385
+ * | `*:read` | `users:read`, `groups:read`, ... |
3386
+ * | `users:read` | only `users:read` |
3387
+ *
3388
+ * Matching is case-insensitive.
3389
+ */
3390
+ declare function cliPermissionMatches(granted: string, required: string): boolean;
3391
+ /** True when any granted permission matches `required`. */
3392
+ declare function cliHasPermission(granted: readonly string[] | undefined, required: string): boolean;
3393
+ /** The subset of `required` permissions not covered by `granted`. */
3394
+ declare function cliMissingPermissions(granted: readonly string[] | undefined, required: readonly string[]): string[];
3395
+ /** Union of permissions, de-duplicated, preserving first-seen order. */
3396
+ declare function cliMergePermissions(...lists: (readonly string[] | undefined)[]): string[];
3397
+ /**
3398
+ * Built-in permissions used by the users module. Other modules define their
3399
+ * own (e.g. `deploy:run`); any string in `resource:action` form works.
3400
+ */
3401
+ /** Permissions for remote CLI server features. */
3402
+ declare const CliServerPermissions: {
3403
+ /** Open a remote shell on a server (`ssh`) */
3404
+ readonly ShellExecute: "shell:execute";
3405
+ };
3406
+ declare const CliUsersPermissions: {
3407
+ readonly UsersRead: "users:read";
3408
+ readonly UsersCreate: "users:create";
3409
+ readonly UsersUpdate: "users:update";
3410
+ readonly UsersDelete: "users:delete";
3411
+ readonly GroupsRead: "groups:read";
3412
+ readonly GroupsCreate: "groups:create";
3413
+ readonly GroupsUpdate: "groups:update";
3414
+ readonly GroupsDelete: "groups:delete";
3415
+ readonly SessionsRead: "sessions:read";
3416
+ readonly SessionsRevoke: "sessions:revoke";
3417
+ readonly AuditRead: "audit:read";
3418
+ readonly AuditClear: "audit:clear";
3419
+ };
3420
+
3421
+ /**
3422
+ * `metadata.requireAuth` (also implied by `requiredGroups` /
3423
+ * `requiredPermissions`): the command needs a signed-in principal.
3424
+ * Active only when an {@link ICliAuthorizationService} is registered.
3425
+ */
3426
+ declare const cliRequireAuthGuard: ICliCommandGuard;
3427
+ /**
3428
+ * `metadata.requiredGroups`: the principal must belong to at least one group.
3429
+ * Active only when an {@link ICliAuthorizationService} is registered.
3430
+ */
3431
+ declare const cliRequiredGroupsGuard: ICliCommandGuard;
3432
+ /**
3433
+ * `metadata.requiredPermissions`: the principal must hold all permissions.
3434
+ * Active only when an {@link ICliAuthorizationService} is registered.
3435
+ */
3436
+ declare const cliRequiredPermissionsGuard: ICliCommandGuard;
3437
+ /**
3438
+ * Guards enforcing access metadata on processors. Registered by the CLI
3439
+ * engine; they do nothing until an auth module registers an
3440
+ * {@link ICliAuthorizationService}.
3441
+ */
3442
+ declare const cliAccessMetadataGuards: ICliCommandGuard[];
3443
+
3444
+ /**
3445
+ * The server a command should use when the user does not name one.
3446
+ *
3447
+ * Prefers the server manager's choice (the default server, else the first
3448
+ * connected one) so a command does not pick a server that is down or that
3449
+ * rejects the user (a protected server they have not signed in to). Falls
3450
+ * back to the first configured server when no manager is available or
3451
+ * nothing is connected, so callers still get a clear error from that server.
3452
+ */
3453
+ declare function cliDefaultServer(context: Pick<ICliExecutionContext, 'services' | 'options'>): CliServerConfig | undefined;
3454
+
2913
3455
  /**
2914
3456
  * Retrieve a parameter's value from the parsed arguments, checking aliases.
2915
3457
  * @param p The parameter descriptor
@@ -3062,7 +3604,7 @@ interface CliThemeInfo {
3062
3604
 
3063
3605
  declare const DefaultThemeInfos: Record<string, CliThemeInfo>;
3064
3606
 
3065
- declare const LIBRARY_VERSION = "2.0.0-beta.13";
3607
+ declare const LIBRARY_VERSION = "2.0.0-beta.14";
3066
3608
  declare const API_VERSION = 2;
3067
3609
 
3068
3610
  /**
@@ -3123,4 +3665,4 @@ declare class BrowserFileTransferService implements ICliFileTransferService {
3123
3665
  private _pickFile;
3124
3666
  }
3125
3667
 
3126
- export { API_VERSION, BrowserFileTransferService, CANCELLATION_ERROR_MESSAGE, CLI_CONFIGURE_STORE_NAME, CancellablePromise, type CliAddUser, CliBackgroundColor, type CliBackgroundServiceStatus, type CliBackgroundServiceType, type CliDateOptions, type CliEngineSnapshot, type CliFactoryProvider, type CliFilePickerOptions, type CliFileResult, CliForegroundColor, type CliFullScreenOptions, type CliHeadersProvider, type CliHttpRequestOptions, CliIcon, type CliLineOptions, CliLogLevel, CliModuleRegistry, type CliMultiSelectOption, type CliMultiSelectOptions, type CliNotification, type CliNotificationLevel, type CliNumberOptions, type CliOptions, type CliPackageSource, type CliPanelConfig, type CliPanelHideAlignment, type CliPanelPaneState, type CliPanelPosition, type CliPanelState, type CliPanelTabState, type CliPercentageProgressBarUpdateValueOptions, type CliProcessCommand, type CliProcessorMetadata, type CliProvider, type CliSelectOption, type CliSelectOptions, type CliServerCapabilities, type CliServerCommandDescriptor, type CliServerConfig, type CliServerOutput, type CliServerResponse, type CliServiceEventHandler, type CliServiceExecutionMode, type CliServiceLogLevel, type CliState, type CliStateConfiguration, type CliTableOptions, type CliTextAnimatorOptions, type CliTheme, type CliThemeCategory, type CliThemeInfo, type CliTypeProvider, type CliUpdateUser, type CliValueProvider, type CliWorkerInboundMessage, type CliWorkerOutboundMessage, DEFAULT_DIR_PERMISSIONS, DEFAULT_FILE_PERMISSIONS, DefaultLibraryAuthor, DefaultThemeInfos, DefaultThemes, type DefaultThemesType, type ICliAuthService, ICliAuthService_TOKEN, type ICliBackgroundService, type ICliBackgroundServiceInfo, type ICliBackgroundServiceRegistry, type ICliClipboard, type ICliCommandAuthor, type ICliCommandChildProcessor, type ICliCommandExecutorService, type ICliCommandParameterDescriptor, type ICliCommandProcessor, type ICliCommandProcessorRegistry, type ICliCompletionContext, type ICliCompletionProvider, ICliCompletionProvider_TOKEN, type ICliConfigurableModule, type ICliConfigurationOption, type ICliDragDropService, ICliDragDropService_TOKEN, type ICliExecutionContext, type ICliExecutionProcess, type ICliFileEntry, type ICliFilePickerProvider, ICliFilePickerProvider_TOKEN, type ICliFileTransferService, ICliFileTransferService_TOKEN, type ICliGlobalParameterHandler, type ICliGroup, type ICliGroupsStoreService, ICliGroupsStoreService_TOKEN, type ICliHttpClient, ICliHttpClient_TOKEN, type ICliInputReader, type ICliKeyValueStore, type ICliLogger, type ICliManagedInterval, type ICliManagedTimer, type ICliModule, type ICliNotifier, type ICliOwnership, type ICliPanelRef, type ICliPercentageProgressBar, type ICliPermissionService, ICliPermissionService_TOKEN, type ICliPingServerService, type ICliProcessEntry, type ICliProcessRegisterOptions, type ICliProcessRegistry, type ICliProcessorHook, type ICliProgressBar, type ICliServerAuthService, ICliServerAuthService_TOKEN, type ICliServerAuthTokenProvider, ICliServerAuthTokenProvider_TOKEN, type ICliServiceContext, type ICliServiceEvent, type ICliServiceLogEntry, type ICliServiceProvider, type ICliSpinner, type ICliStateStore, type ICliTerminalWriter, type ICliTextAnimator, type ICliTranslationService, ICliTranslationService_TOKEN, type ICliUmdModule, type ICliUser, type ICliUserCredentials, type ICliUserSession, type ICliUserSessionService, ICliUserSessionService_TOKEN, type ICliUsersStoreService, ICliUsersStoreService_TOKEN, type ISyntaxHighlightRule, type ISyntaxHighlighter, type ISyntaxTheme, LIBRARY_VERSION, type LineState, ObjectDescriber, type Package, type ServerVersionInfo, ServerVersionNegotiator, type WorkerServiceContext, bootCliModule, bootUmdModule, buildAuthenticatedWebSocketUrl, clearTerminalLine, colorFirstWord, colorizeJson, compareVersions, constants, createWorkerService, delay, derivePanelThemeStyles, enums, formatJson, getConfigValue, getParameterValue, getPluginConfigValue, getRightOfWord, highlightTextWithBg, initializeBrowserEnvironment, loadPanelPosition, nextPanelPosition, resolveConfigurationCategories, resolveHeaders, resolveServerHeaders, satisfiesMinVersion, satisfiesVersionRange, savePanelPosition, stripAnsi, toQueryString, utils, visibleLength };
3668
+ export { API_VERSION, BrowserFileTransferService, CANCELLATION_ERROR_MESSAGE, CLI_CONFIGURE_STORE_NAME, CancellablePromise, type CliAccessAction, CliAccessDeniedError, type CliAddUser, CliBackgroundColor, type CliBackgroundServiceStatus, type CliBackgroundServiceType, type CliCommandGuardResult, type CliDateOptions, type CliEngineSnapshot, type CliFactoryProvider, type CliFilePickerOptions, type CliFileResult, CliForegroundColor, type CliFullScreenOptions, type CliHeadersProvider, CliHttpError, type CliHttpRequestOptions, CliIcon, type CliLineOptions, CliLogLevel, CliModuleRegistry, type CliMultiSelectOption, type CliMultiSelectOptions, type CliNotification, type CliNotificationLevel, type CliNumberOptions, type CliOptions, type CliPackageSource, type CliPanelConfig, type CliPanelHideAlignment, type CliPanelPaneState, type CliPanelPosition, type CliPanelState, type CliPanelTabState, type CliPercentageProgressBarUpdateValueOptions, type CliPermissionDefinition, type CliProcessCommand, type CliProcessorMetadata, type CliProvider, type CliSelectOption, type CliSelectOptions, type CliServerCapabilities, type CliServerCommandDescriptor, type CliServerConfig, type CliServerOutput, CliServerPermissions, type CliServerResponse, type CliServiceEventHandler, type CliServiceExecutionMode, type CliServiceLogLevel, type CliState, type CliStateConfiguration, type CliTableOptions, type CliTextAnimatorOptions, type CliTheme, type CliThemeCategory, type CliThemeInfo, type CliTypeProvider, type CliUpdateUser, CliUsersPermissions, type CliValueProvider, type CliWorkerInboundMessage, type CliWorkerOutboundMessage, DEFAULT_DIR_PERMISSIONS, DEFAULT_FILE_PERMISSIONS, DefaultLibraryAuthor, DefaultThemeInfos, DefaultThemes, type DefaultThemesType, type ICliAuditEntry, type ICliAuditService, ICliAuditService_TOKEN, type ICliAuthService, ICliAuthService_TOKEN, type ICliAuthorizationService, ICliAuthorizationService_TOKEN, type ICliBackgroundService, type ICliBackgroundServiceInfo, type ICliBackgroundServiceRegistry, type ICliClipboard, type ICliCommandAuthor, type ICliCommandChildProcessor, type ICliCommandExecutorService, type ICliCommandGuard, ICliCommandGuard_TOKEN, type ICliCommandParameterDescriptor, type ICliCommandProcessor, type ICliCommandProcessorRegistry, type ICliCompletionContext, type ICliCompletionProvider, ICliCompletionProvider_TOKEN, type ICliConfigurableModule, type ICliConfigurationOption, type ICliDragDropService, ICliDragDropService_TOKEN, type ICliExecutionContext, type ICliExecutionProcess, type ICliFileEntry, type ICliFilePickerProvider, ICliFilePickerProvider_TOKEN, type ICliFileTransferService, ICliFileTransferService_TOKEN, type ICliGlobalParameterHandler, type ICliGroup, type ICliGroupsStoreService, ICliGroupsStoreService_TOKEN, type ICliHttpClient, ICliHttpClient_TOKEN, type ICliInputReader, type ICliKeyValueStore, ICliKeyValueStore_TOKEN, type ICliLogger, type ICliManagedInterval, type ICliManagedTimer, type ICliModule, type ICliNotifier, type ICliOwnership, type ICliPanelRef, type ICliPercentageProgressBar, type ICliPermissionRegistry, ICliPermissionRegistry_TOKEN, type ICliPermissionService, ICliPermissionService_TOKEN, type ICliPingServerService, type ICliPrincipal, type ICliProcessEntry, type ICliProcessRegisterOptions, type ICliProcessRegistry, type ICliProcessorHook, type ICliProgressBar, type ICliProtectedResource, type ICliServerAuthService, ICliServerAuthService_TOKEN, type ICliServerAuthTokenProvider, ICliServerAuthTokenProvider_TOKEN, type ICliServerManager, ICliServerManager_TOKEN, type ICliServiceContext, type ICliServiceEvent, type ICliServiceLogEntry, type ICliServiceProvider, type ICliSessionInfo, type ICliSessionsService, ICliSessionsService_TOKEN, type ICliSpinner, type ICliStateStore, type ICliTerminalWriter, type ICliTextAnimator, type ICliTranslationService, ICliTranslationService_TOKEN, type ICliUmdModule, type ICliUser, type ICliUserCredentials, type ICliUserEvent, type ICliUserEventService, ICliUserEventService_TOKEN, type ICliUserSession, type ICliUserSessionService, ICliUserSessionService_TOKEN, type ICliUsersStoreService, ICliUsersStoreService_TOKEN, type ISyntaxHighlightRule, type ISyntaxHighlighter, type ISyntaxTheme, LIBRARY_VERSION, type LineState, ObjectDescriber, type Package, type ServerVersionInfo, ServerVersionNegotiator, type WorkerServiceContext, appendQueryParams, bootCliModule, bootUmdModule, buildAuthenticatedWebSocketUrl, clearTerminalLine, cliAccessMetadataGuards, cliAuthorize, cliCanAccess, cliDefaultServer, cliEvaluateAccess, cliHasPermission, cliMergePermissions, cliMissingPermissions, cliPermissionMatches, cliRequireAuthGuard, cliRequiredGroupsGuard, cliRequiredPermissionsGuard, colorFirstWord, colorizeJson, compareVersions, constants, createWorkerService, delay, derivePanelThemeStyles, enums, formatJson, getConfigValue, getParameterValue, getPluginConfigValue, getRightOfWord, highlightTextWithBg, initializeBrowserEnvironment, isCliAccessDeniedError, loadPanelPosition, nextPanelPosition, resolveConfigurationCategories, resolveHeaders, resolveServerHeaders, resolveServerWebSocketUrl, satisfiesMinVersion, satisfiesVersionRange, savePanelPosition, stripAnsi, toQueryString, utils, visibleLength };