diff --git a/AGENTS.md b/AGENTS.md index d1b02a0..b3332b6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,14 +22,15 @@ All business logic is located in the `src/` directory: * [`src/client.rs`](src/client.rs): Wrapper around the Keycloak Admin REST API. Handles authentication and provides a **generic CRUD interface** for resources. * [`src/models.rs`](src/models.rs): Strongly-typed Serde representations of Keycloak resources. Implements the `KeycloakResource` and `ResourceMeta` traits. * [`src/inspect.rs`](src/inspect.rs): Scans the remote Keycloak instance and serializes resources into local workspace files using a parallelized pipeline. -* [`src/plan/`](src/plan/): Calculates diffs and writes the plan. Uses the generic planning engine in `generic.rs`. +* [`src/plan/`](src/plan/): Calculates diffs and writes the plan. Uses the generic planning engine in `generic.rs`. Supports collapsed unified diff formatting (3 context lines) by default, `--verbose` full diff view, and interactive expansion choices during confirmation. * [`src/apply/`](src/apply/): Reconciles resources. Uses the generic reconciliation engine in `generic.rs` and stage-specific modules. * [`src/validate.rs`](src/validate.rs): Validates local configurations against expected structures and constraints. * [`src/clean.rs`](src/clean.rs): Removes unreferenced or invalid configuration files from the workspace. -* [`src/cli/`](src/cli/): Interactive CLI scaffolding menu. +* [`src/init.rs`](src/init.rs): Scaffolds the initial `kaji.toml` / `.kaji.toml` configuration files. +* [`src/cli/`](src/cli/): Interactive CLI scaffolding menu. Styled with `dialoguer`'s `ColorfulTheme` and uses `FuzzySelect` for real-time query filtering. Auto-discovers existing realms in the workspace directory. * [`src/utils/secrets/`](src/utils/secrets/): Manages secret resolution (Env, HashiCorp Vault). * [`src/utils/yaml.rs`](src/utils/yaml.rs): Handles YAML serialization, sorting, and profile-specific deep-merging. -* [`src/utils/ui.rs`](src/utils/ui.rs): CLI visual formatting, progress bars, emojis, and styling. +* [`src/utils/ui.rs`](src/utils/ui.rs): CLI visual formatting, progress bars, emojis, and styling. Contains DialoguerUi which maps console prompts to ColorfulTheme and FuzzySelect. --- @@ -44,6 +45,14 @@ To prevent race conditions, resources are reconciled sequentially across stages: | **Stage 2** | Clients, Client Scopes, Authentication Flows, Required Actions, Groups | Structure | | **Stage 3** | Users, Authenticator Configs, Components, Keys | Data & Final Config | +## ๐Ÿ”„ Keycloak Resource Enrichment + +During the reconciliation (`apply`) process, Keycloak may enrich resources with default values, read-only system attributes, or server-assigned identifiers (IDs). When `kaji` detects differences between the local representation and the enriched one returned by Keycloak: +1. It recursively maps any user-defined secret placeholders (e.g. `${VAR_NAME}`) from the original local file to the enriched representation to prevent them from being lost or overwritten by redacted/actual secret values. +2. It prompts the user (defaulting to Yes) to update the local representation to match the enriched Keycloak representation. +3. If the `--yes` (`-y`) option flag is passed, the update is accepted automatically without prompting. +4. Any newly generated secrets (such as client secrets) are extracted and appended to the secrets file. + --- ## ๐ŸŒ Environment Profiles & Overlays diff --git a/Cargo.lock b/Cargo.lock index 9fc9a2c..42a64d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,6 +447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f104b501bf2364e78d0d3974cbc774f738f5865306ed128e1e0d7499c0ad96" dependencies = [ "console", + "fuzzy-matcher", "shell-words", "tempfile", "zeroize", @@ -656,6 +657,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -1928,6 +1938,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + [[package]] name = "tinystr" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index fb24035..67bafc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ similar = "2.7.0" async-trait = "0.1.86" async-recursion = "1.1.1" console = "0.16.3" -dialoguer = "0.12.0" +dialoguer = { version = "0.12.0", features = ["fuzzy-select"] } futures = "0.3.32" indicatif = "0.18.4" diff --git a/GEMINI.md b/GEMINI.md index 519adc8..eb1cf06 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -21,6 +21,7 @@ This document serves as the internal developer guide for `kaji`. It explains the - `src/utils/secrets/`: Manages secret resolution (Env, Vault, etc.). - `src/utils/yaml.rs`: Handles YAML deep-merging and profile-specific overlays. - `src/utils/ui.rs`: Centralized module for CLI output formatting, emoji management, and **indicatif progress bars**. +- `src/init.rs`: Scaffolds the initial `kaji.toml` / `.kaji.toml` configuration files. --- @@ -33,6 +34,14 @@ To prevent race conditions and ensure correct dependency handling, `apply` is ex 3. **Stage 2**: Clients, Client Scopes, Authentication Flows, Required Actions, Groups (Structure). 4. **Stage 3**: Users, Authenticator Configs, Components, Keys (Data & Final Config). +## ๐Ÿ”„ Keycloak Resource Enrichment + +During the reconciliation (`apply`) process, Keycloak may enrich resources with default values, read-only system attributes, or server-assigned identifiers (IDs). When `kaji` detects differences between the local representation and the enriched one returned by Keycloak: +1. It recursively maps any user-defined secret placeholders (e.g. `${VAR_NAME}`) from the original local file to the enriched representation to prevent them from being lost or overwritten by redacted/actual secret values. +2. It prompts the user (defaulting to Yes) to update the local representation to match the enriched Keycloak representation. +3. If the `--yes` (`-y`) option flag is passed, the update is accepted automatically without prompting. +4. Any newly generated secrets (such as client secrets) are extracted and appended to the secrets file. + --- ## ๐ŸŒ Environment Profiles & Overlays @@ -84,6 +93,22 @@ To support a new Keycloak resource (e.g., "Event Listeners"): --- +## ๐Ÿ“บ Terminal UI & Diff Viewer Enhancements + +### 1. Minimal Unified Diffs (Collapsed by Default) +To reduce terminal clutter, `kaji plan` and `kaji drift` default to showing collapsed unified diffs (with 3 context lines around changes). A `--verbose` or `-v` flag allows users to output full file diffs. + +### 2. Interactive Diff Expansion +During `kaji plan --interactive`, the prompt is a selection menu with `Yes` (include change), `No` (skip change), and `Show Full Diff` (expand to full verbose diff). Selecting `Show Full Diff` displays the complete diff and prompts the user again. + +### 3. Styled Fuzzy Scaffolding Menu +The interactive menu (`kaji cli`) utilizes `dialoguer::theme::ColorfulTheme` for polished, colorful CLI prompts. It replaces standard selects with `dialoguer::FuzzySelect`, allowing users to type to search and filter options instantly. + +### 4. Workspace Realm Auto-Discovery +All scaffolding prompts dynamically scan the workspace to discover existing realms. The user is presented with a `FuzzySelect` list of discovered realms plus a `` option, avoiding manual typing for existing projects. + +--- + ## ๐Ÿงช Testing Strategy `kaji` employs a multi-layered testing strategy: diff --git a/JULES.md b/JULES.md index 66198b8..77d3a00 100644 --- a/JULES.md +++ b/JULES.md @@ -15,6 +15,7 @@ Detailed guidelines are located under the `.jules/` directory: ## ๐Ÿ—๏ธ Architecture & Operations Summary * **Diff Engine & Reconciler**: The workflow calculates differences between the desired local YAML state and the Keycloak Admin API state, generating a `.kajiplan` file, and applying it sequentially in stages (Stage 0: Realms; Stage 1: IDPs/Roles; Stage 2: Clients/Scopes/Flows/Groups; Stage 3: Users/Authenticator Configs/Components/Keys). +* **Project Bootstrapping**: Scaffold project configuration files (`kaji.toml` / `.kaji.toml`) using the `kaji init` command. * **Overlay Deep Merging**: Keycloak resources can be customized per-environment by applying overlays (e.g. `roles/admin.prod.yaml` over `roles/admin.yaml`). * **Documentation Rule**: Always update [README.md](README.md), [AGENTS.md](AGENTS.md), [JULES.md](JULES.md), and [.jules/](.jules/) files when changing the codebase. * **Quality Commands**: diff --git a/README.md b/README.md index 528c9e5..3ad96b2 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ $ kaji cli - **Declarative State**: Define your desired Keycloak state in human-readable YAML files. - **Environment Profiles & Overlays**: Manage multiple environments (Dev, Staging, Prod) with zero configuration duplication. - **Dependency-Aware Reconciliation**: Guaranteed correct application order through staged reconciliation (e.g., Realms -> Roles -> Users). +- **Bootstrapping & Scaffolding**: Easily initialize new project configurations (`kaji.toml` / `.kaji.toml`) with the `init` command. - **Inspect & Export**: Bootstrap your project by exporting existing Keycloak configurations to local files. - **Dry-Run Planning**: Preview exactly what changes will be applied with detailed diffs and summaries. - **Interactive Review**: Confirm individual changes before they are applied to the server using the `--review` flag. @@ -230,12 +231,16 @@ kaji validate ``` ### `plan` -Calculates the "diff" between local files and the remote server. +Calculates the "diff" between local files and the remote server. By default, it shows a minimal, clean unified diff (collapsed with 3 lines of context). ```bash # Plan for a specific profile kaji plan --profile prod -# Interactive: decide for each change whether to include it in the plan +# Show full resource diffs instead of collapsed unified diffs +kaji plan --verbose + +# Interactive: decide for each change whether to include it. +# Prompts you with: Yes (include), No (skip), Show Full Diff (to expand) kaji plan --interactive ``` @@ -250,9 +255,12 @@ kaji apply --profile prod --review ``` ### `drift` -A shortcut for `plan --changes-only`. +A shortcut for `plan --changes-only`. By default, it prints collapsed unified diffs. ```bash kaji drift --profile prod + +# Show full resource diffs for configuration drift +kaji drift --verbose ``` ### `clean` @@ -267,6 +275,16 @@ An interactive menu to generate resource scaffolds or perform quick actions. kaji cli ``` +### `init` +Scaffolds an initial `kaji.toml` / `.kaji.toml` project configuration. Automatically pre-fills settings from the environment where available. +```bash +# Non-interactive mode (uses environment variables to pre-fill, otherwise writes empty/default configuration) +kaji init + +# Interactive mode (asks you for configuration parameters step-by-step) +kaji init --interactive +``` + --- ## ๐Ÿ” Secret Management diff --git a/docs/index.html b/docs/index.html index 4aeafb5..8318c06 100644 --- a/docs/index.html +++ b/docs/index.html @@ -79,18 +79,19 @@

kaji plan
$ kaji plan --interactive
-// Calculating diff for realm 'master'...
+๐Ÿš€ Planning changes for realm: master
 
-  Clients:
-    [+] my-new-app         Create
-    [~] admin-cli           Update
-        root_url: "http://localhost" → "https://idp.example.com"
-    [-] legacy-app          Delete
+๐Ÿ“ Changes for Client admin-cli:
+@@ -15,5 +15,5 @@
+   protocol: openid-connect
+-  rootUrl: "http://localhost"
++  rootUrl: "https://idp.example.com"
+   publicClient: false
 
-  Roles:
-    [+] billing-manager    Create
-
-? Apply change to client 'my-new-app'? 
+? Include this change in the plan? +> Yes + No + Show Full Diff