keycloak-api-manager 6.0.2 → 6.0.4

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/docs/api/roles.md CHANGED
@@ -2,7 +2,12 @@
2
2
 
3
3
  Realm and client role management, including composite roles.
4
4
 
5
- **Namespace:** `KeycloakManager.roles`
5
+ Namespace: KeycloakManager.roles
6
+
7
+ ## Overview
8
+
9
+ This handler manages realm roles and composite relationships.
10
+ It covers CRUD, user-role lookup, and composite role operations for realm and client roles.
6
11
 
7
12
  ## Role CRUD
8
13
 
@@ -16,25 +21,28 @@ Create a realm role.
16
21
  ### find(filters)
17
22
  List realm roles.
18
23
 
19
- - **Optional**: `first`, `max`, `search`, `briefRepresentation`
24
+ - **Optional**: `first`, `max`, `search`, `briefRepresentation`, `realm`
20
25
  - **Returns**: Promise<Array<RoleRepresentation>>
21
26
 
22
27
  ### findOneByName(filters)
23
28
  Get role by name.
24
29
 
25
30
  - **Required**: `filters.name` (string)
31
+ - **Optional**: `filters.realm` (string)
26
32
  - **Returns**: Promise<RoleRepresentation>
27
33
 
28
34
  ### findOneById(filters)
29
35
  Get role by id.
30
36
 
31
37
  - **Required**: `filters.id` (string)
38
+ - **Optional**: `filters.realm` (string)
32
39
  - **Returns**: Promise<RoleRepresentation>
33
40
 
34
41
  ### updateByName(filters, role_dictionary)
35
42
  Update role by name.
36
43
 
37
44
  - **Required**: `filters.name` (string)
45
+ - **Optional**: `filters.realm` (string)
38
46
  - **Required**: `role_dictionary` (partial role)
39
47
  - **Returns**: Promise<void>
40
48
 
@@ -42,6 +50,7 @@ Update role by name.
42
50
  Update role by id.
43
51
 
44
52
  - **Required**: `filters.id` (string)
53
+ - **Optional**: `filters.realm` (string)
45
54
  - **Required**: `role_dictionary` (partial role)
46
55
  - **Returns**: Promise<void>
47
56
 
@@ -49,6 +58,7 @@ Update role by id.
49
58
  Delete role by name.
50
59
 
51
60
  - **Required**: `filters.name` (string)
61
+ - **Optional**: `filters.realm` (string)
52
62
  - **Returns**: Promise<void>
53
63
 
54
64
  ## Composite Roles
@@ -56,27 +66,31 @@ Delete role by name.
56
66
  ### createComposite(filters, roles)
57
67
  Add composites to a realm role.
58
68
 
59
- - **Required**: `filters.roleName` (string)
69
+ - **Required**: `filters.roleId` (string)
70
+ - **Optional**: `filters.realm` (string)
60
71
  - **Required**: `roles` (Array<{id,name}>), realm or client roles
61
72
  - **Returns**: Promise<void>
62
73
 
63
74
  ### getCompositeRoles(filters)
64
75
  Get all composites for a role.
65
76
 
66
- - **Required**: `filters.roleName` (string)
77
+ - **Required**: `filters.id` (string)
78
+ - **Optional**: `filters.realm` (string)
67
79
  - **Returns**: Promise<Array<RoleRepresentation>>
68
80
 
69
81
  ### getCompositeRolesForRealm(filters)
70
82
  Get realm-level composites.
71
83
 
72
- - **Required**: `filters.roleName` (string)
84
+ - **Required**: `filters.id` (string)
85
+ - **Optional**: `filters.realm` (string)
73
86
  - **Returns**: Promise<Array<RoleRepresentation>>
74
87
 
75
88
  ### getCompositeRolesForClient(filters)
76
89
  Get client-level composites.
77
90
 
78
- - **Required**: `filters.roleName` (string)
79
- - **Required**: `filters.clientUniqueId` (client UUID)
91
+ - **Required**: `filters.id` (string)
92
+ - **Required**: `filters.clientId` (string, client UUID)
93
+ - **Optional**: `filters.realm` (string)
80
94
  - **Returns**: Promise<Array<RoleRepresentation>>
81
95
 
82
96
  ## Users with Role
@@ -85,6 +99,7 @@ Get client-level composites.
85
99
  List users that have a specific realm role.
86
100
 
87
101
  - **Required**: `filters.name` (role name)
102
+ - **Optional**: `filters.realm` (string)
88
103
  - **Optional**: `first`, `max`
89
104
  - **Returns**: Promise<Array<UserRepresentation>>
90
105
 
@@ -94,6 +109,21 @@ List users that have a specific realm role.
94
109
  await KeycloakManager.roles.create({ name: 'realm-admin' });
95
110
  const role = await KeycloakManager.roles.findOneByName({ name: 'realm-admin' });
96
111
  const users = await KeycloakManager.roles.findUsersWithRole({ name: 'realm-admin' });
112
+
113
+ // Composite role with one realm role and one client role
114
+ await KeycloakManager.roles.createComposite(
115
+ { roleId: compositeRoleId },
116
+ [
117
+ { id: realmRoleId, name: 'test-role-1' },
118
+ { id: clientRoleId, name: 'client-role-a', clientRole: true, containerId: clientUuid }
119
+ ]
120
+ );
121
+
122
+ const realmComposites = await KeycloakManager.roles.getCompositeRolesForRealm({ id: compositeRoleId });
123
+ const clientComposites = await KeycloakManager.roles.getCompositeRolesForClient({
124
+ id: compositeRoleId,
125
+ clientId: clientUuid,
126
+ });
97
127
  ```
98
128
 
99
129
  ## See Also
@@ -2,37 +2,62 @@
2
2
 
3
3
  Read Keycloak server capabilities and runtime metadata.
4
4
 
5
- **Namespace:** `KeycloakManager.serverInfo`
5
+ Namespace: KeycloakManager.serverInfo
6
+
7
+ ## Overview
8
+
9
+ Use this handler to inspect server capabilities before enabling advanced features in automation.
10
+ It is useful for diagnostics and compatibility checks in CI pipelines.
6
11
 
7
12
  ## Methods
8
13
 
9
14
  ### getInfo()
10
- Get full server-info payload.
11
15
 
12
- - **Params**: none
13
- - **Returns**: Promise<object>
16
+ Fetch the full server-info payload from the configured realm context.
17
+
18
+ Parameters:
19
+
20
+ - none
21
+
22
+ Returns:
23
+
24
+ - Promise<object>: full server info payload.
25
+
26
+ Common top-level sections returned by Keycloak include:
14
27
 
15
- The payload typically includes:
16
- - `systemInfo`
17
- - `memoryInfo`
18
- - `profileInfo`
19
- - `themes`
20
- - `providers`
21
- - `componentTypes`
22
- - `passwordPolicies`
23
- - `protocolMapperTypes`
24
- - `clientInstallations`
25
- - `enums`
28
+ - systemInfo
29
+ - memoryInfo
30
+ - profileInfo
31
+ - themes
32
+ - providers
33
+ - componentTypes
34
+ - passwordPolicies
35
+ - protocolMapperTypes
36
+ - clientInstallations
37
+ - enums
26
38
 
27
- ## Example
39
+ Example: basic inspection
28
40
 
29
41
  ```js
30
42
  const info = await KeycloakManager.serverInfo.getInfo();
31
43
 
32
44
  console.log('Keycloak version:', info.systemInfo?.version);
33
45
  console.log('Available themes:', Object.keys(info.themes || {}));
34
- console.log('Available provider categories:', Object.keys(info.providers || {}));
46
+ console.log('Provider categories:', Object.keys(info.providers || {}));
47
+ ```
48
+
49
+ Example: feature guard before workflow
50
+
51
+ ```js
52
+ const info = await KeycloakManager.serverInfo.getInfo();
53
+ const hasOrganizationFeature = Boolean(info.profileInfo?.features?.organization);
54
+
55
+ if (!hasOrganizationFeature) {
56
+ throw new Error('Organization feature is not enabled on this Keycloak server.');
57
+ }
35
58
  ```
36
59
 
37
60
  ## See Also
61
+
38
62
  - [API Reference](../api-reference.md)
63
+ - [Keycloak Setup and Feature Flags](../keycloak-setup.md)
@@ -2,28 +2,72 @@
2
2
 
3
3
  Manage realm user-profile configuration and metadata.
4
4
 
5
- **Namespace:** `KeycloakManager.userProfile`
5
+ Namespace: KeycloakManager.userProfile
6
+
7
+ ## Overview
8
+
9
+ This handler manages declarative user-profile schema in a realm.
10
+ It allows you to inspect current schema, update it, and read resolved metadata (validators, capabilities, attribute model).
11
+
12
+ Note: endpoints are accessed through direct REST calls in the handler for compatibility across admin-client versions.
6
13
 
7
14
  ## Methods
8
15
 
9
16
  ### getConfiguration(filter)
10
- Get user-profile configuration for realm.
11
17
 
12
- - **Optional**: realm context fields
13
- - **Returns**: Promise<object>
18
+ Get the current declarative user-profile configuration.
19
+
20
+ Parameters:
21
+
22
+ - filter (object, optional):
23
+ - realm (string, optional): override target realm.
24
+
25
+ Returns:
26
+
27
+ - Promise<object>: current profile configuration.
14
28
 
15
29
  ### updateConfiguration(filter, userProfileConfig)
30
+
16
31
  Update user-profile configuration.
17
32
 
18
- - **Optional**: realm context fields
19
- - **Required**: `userProfileConfig` (full/partial config object)
20
- - **Returns**: Promise<void|object>
33
+ Parameters:
34
+
35
+ - filter (object, optional):
36
+ - realm (string, optional): override target realm.
37
+ - userProfileConfig (object, required): full or partial schema payload.
38
+
39
+ Common top-level fields:
40
+
41
+ - attributes (array): attribute definitions.
42
+ - groups (array, optional): grouped attributes.
43
+ - unmanagedAttributePolicy (string, optional)
44
+
45
+ Common attribute fields:
46
+
47
+ - name (string, required): attribute key.
48
+ - displayName (string, optional)
49
+ - required (object, optional): required rules.
50
+ - permissions (object, optional): view/edit permissions.
51
+ - validations (object, optional): validation rules.
52
+ - annotations (object, optional): UI/metadata annotations.
53
+ - multivalued (boolean, optional): enable list values.
54
+
55
+ Returns:
56
+
57
+ - Promise<void|object>: usually no content (204), or response payload if provided by server.
21
58
 
22
59
  ### getMetadata(filter)
23
- Get resolved user-profile metadata.
24
60
 
25
- - **Optional**: realm context fields
26
- - **Returns**: Promise<object>
61
+ Get user-profile metadata resolved by the server.
62
+
63
+ Parameters:
64
+
65
+ - filter (object, optional):
66
+ - realm (string, optional): override target realm.
67
+
68
+ Returns:
69
+
70
+ - Promise<object>: metadata payload (validators, resolved attributes, capabilities).
27
71
 
28
72
  ## Common User Profile Structure
29
73
 
@@ -56,6 +100,7 @@ await KeycloakManager.userProfile.updateConfiguration({}, {
56
100
  });
57
101
 
58
102
  const metadata = await KeycloakManager.userProfile.getMetadata();
103
+ console.log('Available validators:', Object.keys(metadata.validators || {}));
59
104
  ```
60
105
 
61
106
  ## See Also
@@ -5,7 +5,7 @@ Complete API documentation for keycloak-api-manager.
5
5
  ## Table of Contents
6
6
 
7
7
  ### Guides
8
- - [OIDC Migration Plan](../OIDC_MIGRATION_PLAN.md) - Deprecation status and migration notes to keycloak-express-middleware
8
+ - [OIDC Migration Plan](../OIDC_MIGRATION_PLAN.md) - Migration notes for legacy OIDC helpers
9
9
 
10
10
  ### Core API
11
11
  - [Configuration & Authentication](api/configuration.md) - Setup, authentication, and lifecycle management
@@ -61,7 +61,8 @@ await KeycloakManager.configure({
61
61
  tokenLifeSpan: 60
62
62
  });
63
63
 
64
- // Switch to different realm
64
+ // Alternative after configure(): switch runtime context without calling
65
+ // configure() again (no new login/token flow is performed).
65
66
  KeycloakManager.setConfig({ realmName: 'my-realm' });
66
67
 
67
68
  // Use handlers
@@ -79,10 +80,7 @@ KeycloakManager.stop();
79
80
  | `configure()` | Authentication and setup | Core |
80
81
  | `setConfig()` | Runtime configuration | Core |
81
82
  | `getToken()` | Get current access/refresh token pair | Core |
82
- | `login()` | Deprecated OIDC token endpoint wrapper (moved to keycloak-express-middleware) | Core |
83
- | `generateAuthorizationUrl()` | Deprecated PKCE helper (moved to keycloak-express-middleware) | Core |
84
- | `loginPKCE()` | Deprecated PKCE token exchange helper (moved to keycloak-express-middleware) | Core |
85
- | `auth()` | Deprecated backward-compatible alias of `login()` | Core |
83
+ | Legacy OIDC helpers | Backward-compatibility methods (`login`, `generateAuthorizationUrl`, `loginPKCE`, `auth`) | Core |
86
84
  | `stop()` | Stop token refresh timer | Core |
87
85
  | `realms` | Realm management | realmsHandler |
88
86
  | `users` | User management | usersHandler |
@@ -99,6 +97,8 @@ KeycloakManager.stop();
99
97
  | `clientPolicies` | Client policy management | clientPoliciesHandler |
100
98
  | `serverInfo` | Server information | serverInfoHandler |
101
99
 
100
+ For deprecation status and migration guidance, see [README - OIDC Deprecation Notice](../README.md#oidc-deprecation-notice).
101
+
102
102
  ## Parameter Conventions
103
103
 
104
104
  Throughout the API:
@@ -15,10 +15,9 @@ This package exposes a single runtime (`index.js`) that initializes one Keycloak
15
15
  - Keeps active session/token management in place.
16
16
 
17
17
  3. `login(credentials)`
18
- - Direct token endpoint call for explicit OIDC login/token flows.
19
- - Intended for application-level third-party authentication use-cases.
18
+ - Legacy OIDC helper kept for backward compatibility.
20
19
  - Does not mutate the internal admin client session established by `configure()`.
21
- - `auth(credentials)` remains available as backward-compatible alias.
20
+ - For deprecation and migration guidance, see the README OIDC Deprecation Notice.
22
21
 
23
22
  4. `stop()`
24
23
  - Stops refresh timer for clean process termination.
@@ -1,21 +1,8 @@
1
- # PKCE Login Flow (Deprecated In This Package)
1
+ # PKCE Login Flow
2
2
 
3
- This package is focused on Keycloak Admin API resource management.
3
+ PKCE and user-authentication helpers in this package are deprecated and retained only for backward compatibility.
4
4
 
5
- PKCE and user-authentication helpers in this package are deprecated since v6.0.0 and kept only for backward compatibility:
6
-
7
- - `generateAuthorizationUrl(options)`
8
- - `loginPKCE(credentials)`
9
- - `login(credentials)`
10
- - `auth(credentials)`
11
-
12
- These methods are planned for removal in v7.0.0.
13
-
14
- For production user authentication flows (including Authorization Code + PKCE), use:
15
-
16
- - https://github.com/smartenv-crs4/keycloak-express-middleware
17
-
18
- Migration references:
5
+ For the canonical deprecation notice and migration path, see:
19
6
 
7
+ - [README - OIDC Deprecation Notice](../../README.md#oidc-deprecation-notice)
20
8
  - [OIDC Migration Plan](../../OIDC_MIGRATION_PLAN.md)
21
- - [Configuration & Authentication](../api/configuration.md)
@@ -1,43 +1,5 @@
1
1
  # Test Configuration
2
2
 
3
- Test configuration is managed through `propertiesmanager` with layered files.
3
+ This file has been merged into the unified [Testing Guide](testing.md).
4
4
 
5
- ## Files and Priority
6
-
7
- 1. `test/config/default.json` (committed defaults)
8
- 2. `test/config/secrets.json` (gitignored sensitive values)
9
- 3. `test/config/local.json` (gitignored machine-specific overrides)
10
-
11
- The active section is selected by `NODE_ENV` (defaults to `test` in suite bootstrap).
12
-
13
- ## Required Keys
14
-
15
- - `test.keycloak.baseUrl`
16
- - `test.keycloak.realmName`
17
- - `test.keycloak.clientId`
18
- - `test.keycloak.username`
19
- - `test.keycloak.password` (typically in `secrets.json`)
20
- - `test.keycloak.grantType`
21
-
22
- ## Example `secrets.json`
23
-
24
- ```json
25
- {
26
- "test": {
27
- "keycloak": {
28
- "password": "admin"
29
- },
30
- "realm": {
31
- "user": {
32
- "password": "test-password"
33
- }
34
- }
35
- }
36
- }
37
- ```
38
-
39
- ## Security Rules
40
-
41
- - Never commit `secrets.json`.
42
- - Never commit production credentials.
43
- - Keep `default.json` non-sensitive.
5
+ See [Testing Guide — Test Configuration](testing.md#test-configuration) for all config details.
package/docs/testing.md CHANGED
@@ -1,6 +1,199 @@
1
1
  # Testing Guide
2
2
 
3
- The test suite validates the package against a real Keycloak server.
3
+ The test suite validates the package against a real Keycloak server. This guide covers both test environment setup and configuration.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Quick Start](#quick-start-end-to-end)
8
+ - [Test Configuration](#test-configuration)
9
+ - [Test Architecture](#test-architecture)
10
+ - [Test Layout](#current-test-layout)
11
+ - [Commands](#commands)
12
+ - [HTTPS Variant](#https-variant)
13
+ - [Setup Flow](#setup-flow)
14
+ - [Writing New Tests](#writing-new-tests)
15
+
16
+ ---
17
+
18
+ ## Quick Start (End-to-End)
19
+
20
+ ### 1) Install dependencies
21
+
22
+ ```bash
23
+ npm install
24
+ npm --prefix test install
25
+ ```
26
+
27
+ ### 2) Prepare local test config
28
+
29
+ Create local override files from the provided examples:
30
+
31
+ ```bash
32
+ cp test/config/local.json.example test/config/local.json
33
+ cp test/config/secrets.json.example test/config/secrets.json
34
+ ```
35
+
36
+ Then edit:
37
+
38
+ - `test/config/local.json` to set the Keycloak URL you can reach locally.
39
+ - `test/config/secrets.json` to set admin credentials.
40
+
41
+ For local Docker on default HTTP port:
42
+
43
+ ```json
44
+ {
45
+ "test": {
46
+ "keycloak": {
47
+ "baseUrl": "http://127.0.0.1:8080",
48
+ "password": "admin"
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### 3) Prepare Keycloak for tests (choose one mode)
55
+
56
+ Choose one of the following modes.
57
+
58
+ #### Mode A: Existing Keycloak instance (no Docker startup here)
59
+
60
+ If you already have a reachable Keycloak instance:
61
+
62
+ - set `test.keycloak.baseUrl` in `test/config/local.json` to that instance URL
63
+ - ensure admin credentials in `test/config/secrets.json` are valid for that instance
64
+ - skip any startup command and run tests directly
65
+
66
+ Example using an existing instance:
67
+
68
+ ```json
69
+ {
70
+ "test": {
71
+ "keycloak": {
72
+ "baseUrl": "https://my-keycloak.company.net"
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ Then run:
79
+
80
+ ```bash
81
+ npm test
82
+ ```
83
+
84
+ #### Mode B: Automated setup with `npm run setup-keycloak`
85
+
86
+ Use this when you do not already have a ready instance and want the helper to provision one.
87
+
88
+ ```bash
89
+ npm run setup-keycloak
90
+ ```
91
+
92
+ What this command does:
93
+
94
+ - runs an interactive setup (local or remote, HTTP or HTTPS)
95
+ - starts Keycloak via Docker Compose in the selected mode
96
+ - waits for readiness
97
+ - updates `test/config/default.json` with the generated `test.keycloak.baseUrl`
98
+
99
+ #### Mode C: Manual Docker startup
100
+
101
+ Use this if you prefer full manual control instead of the setup helper:
102
+
103
+ ```bash
104
+ docker compose -f test/docker-keycloak/docker-compose.yml up -d
105
+ ```
106
+
107
+ Wait until ready:
108
+
109
+ ```bash
110
+ docker compose -f test/docker-keycloak/docker-compose.yml ps
111
+ curl -f http://127.0.0.1:8080/health/ready
112
+ ```
113
+
114
+ ### 4) Run tests
115
+
116
+ ```bash
117
+ npm test
118
+ ```
119
+
120
+ ### 5) Stop environment (optional but recommended)
121
+
122
+ ```bash
123
+ docker compose -f test/docker-keycloak/docker-compose.yml down
124
+ ```
125
+
126
+ To also remove container volumes:
127
+
128
+ ```bash
129
+ docker compose -f test/docker-keycloak/docker-compose.yml down -v
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Test Configuration
135
+
136
+ Test configuration uses `propertiesmanager` with a layered file strategy. Files are merged in this priority order (higher overrides lower):
137
+
138
+ 1. `test/config/default.json` — committed defaults, non-sensitive
139
+ 2. `test/config/secrets.json` — gitignored, admin credentials and passwords
140
+ 3. `test/config/local.json` — gitignored, machine-specific host/port overrides
141
+
142
+ The active section is selected by `NODE_ENV` (defaults to `test` in suite bootstrap).
143
+
144
+ ### Required Configuration Keys
145
+
146
+ | Key | Description |
147
+ |-----|-------------|
148
+ | `test.keycloak.baseUrl` | Keycloak server URL |
149
+ | `test.keycloak.realmName` | Realm used for authentication |
150
+ | `test.keycloak.clientId` | Client ID (usually `admin-cli`) |
151
+ | `test.keycloak.username` | Admin username |
152
+ | `test.keycloak.password` | Admin password (put in `secrets.json`) |
153
+ | `test.keycloak.grantType` | Usually `password` |
154
+
155
+ ### Recommended Pattern
156
+
157
+ - Keep defaults and non-sensitive values in `default.json`.
158
+ - Put admin passwords and test user passwords in `secrets.json`.
159
+ - Put local machine-specific URLs/ports in `local.json`.
160
+
161
+ Example `local.json`:
162
+
163
+ ```json
164
+ {
165
+ "test": {
166
+ "keycloak": {
167
+ "baseUrl": "http://127.0.0.1:8080"
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ Example `secrets.json`:
174
+
175
+ ```json
176
+ {
177
+ "test": {
178
+ "keycloak": {
179
+ "password": "your-admin-password-here"
180
+ },
181
+ "realm": {
182
+ "user": {
183
+ "password": "test-password"
184
+ }
185
+ }
186
+ }
187
+ }
188
+ ```
189
+
190
+ ### Security Rules
191
+
192
+ - Never commit `secrets.json` or `local.json`.
193
+ - Never commit production credentials.
194
+ - Keep `default.json` non-sensitive.
195
+
196
+ ---
4
197
 
5
198
  ## Test Architecture
6
199
 
@@ -12,6 +205,8 @@ The suite uses a shared realm strategy:
12
205
 
13
206
  This improves speed and keeps the environment deterministic.
14
207
 
208
+ ---
209
+
15
210
  ## Current Test Layout
16
211
 
17
212
  ```text
@@ -26,9 +221,14 @@ test/
26
221
  testConfig.js
27
222
  ```
28
223
 
224
+ ---
225
+
29
226
  ## Commands
30
227
 
31
228
  ```bash
229
+ # interactive provisioning helper (starts docker and sets baseUrl)
230
+ npm run setup-keycloak
231
+
32
232
  # full suite
33
233
  npm test
34
234
 
@@ -40,6 +240,41 @@ npm --prefix test test -- --grep "Organizations Handler Tests"
40
240
  npm --prefix test test -- --grep "Matrix -"
41
241
  ```
42
242
 
243
+ ### Command Difference: `npm test` vs `npm --prefix test test`
244
+
245
+ - `npm test` (from repository root): runs the root test script, which first installs test workspace dependencies and then executes the suite.
246
+ - `npm --prefix test test`: runs the test workspace script directly, without performing the install step.
247
+
248
+ Current root script behavior:
249
+
250
+ ```text
251
+ npm test => npm --prefix test install && npm --prefix test test
252
+ ```
253
+
254
+ Practical rule:
255
+
256
+ - use `npm test` when setting up a fresh environment or after dependency changes
257
+ - use `npm --prefix test test` for faster repeated runs when dependencies are already installed
258
+
259
+ ---
260
+
261
+ ## HTTPS Variant
262
+
263
+ For HTTPS-like environments use the dedicated compose file:
264
+
265
+ ```bash
266
+ export KEYCLOAK_CERT_PATH=/absolute/path/to/certs
267
+ export KEYCLOAK_HOSTNAME=keycloak.local
268
+ docker compose -f test/docker-keycloak/docker-compose-https.yml up -d
269
+ ```
270
+
271
+ The cert directory must contain:
272
+
273
+ - `keycloak.crt`
274
+ - `keycloak.key`
275
+
276
+ ---
277
+
43
278
  ## Setup Flow
44
279
 
45
280
  `test/support/setup.js` runs before all suites and executes `test/support/enableServerFeatures.js` to provision:
@@ -52,6 +287,10 @@ npm --prefix test test -- --grep "Matrix -"
52
287
  - client scope
53
288
  - fine-grained permissions (when feature-enabled)
54
289
 
290
+ The same bootstrap also performs cleanup in global teardown by deleting the shared test realm.
291
+
292
+ ---
293
+
55
294
  ## Writing New Tests
56
295
 
57
296
  - Import config from `test/testConfig.js`.