diff --git a/.jules/testing.md b/.jules/testing.md index 3e13e5d..659bff7 100644 --- a/.jules/testing.md +++ b/.jules/testing.md @@ -19,13 +19,13 @@ This document provides context and guidelines for Google Jules when writing, ref 2. **Tokio for Async Tests**: * Use `#[tokio::test]` for asynchronous test cases. 3. **Mockito**: - * Optionally used in older tests to mock external HTTP responses (though Axum is preferred for Keycloak API mocking). + * Optionally used in older tests to mock external HTTP responses (though Axum is preferred for Keycloak API mocking). Can also be used to test request timeout scenarios by using `with_chunked_body` to introduce simulated response delays. 4. **Tempfile**: * Use `tempfile::tempdir()` to create temporary workspaces for reading/writing configuration files during tests to avoid polluting the host system. 5. **Cargo Tarpaulin**: - * Used to measure test coverage. Run coverage checks with: + * Used to measure test coverage. The codebase maintains a strict **95% minimum code coverage** policy. Run coverage checks with: ```bash - cargo tarpaulin --out Xml + cargo tarpaulin ``` ## Guidelines for Writing Tests @@ -37,3 +37,4 @@ This document provides context and guidelines for Google Jules when writing, ref 1. A validation test in [validate_test.rs](tests/validate_test.rs). 2. An integration test verifying planning and reconciliation in [plan_test.rs](tests/plan_test.rs) or [apply_test.rs](tests/apply_test.rs). 3. A model coverage test in [models_coverage_test.rs](tests/models_coverage_test.rs). + 4. Verification that total project code coverage meets the **95% threshold**. Avoid writing "fake" or empty test cases to inflate coverage; all tests must validate realistic execution, errors, or configuration edge cases. diff --git a/AGENTS.md b/AGENTS.md index b3332b6..3c7a121 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ All business logic is located in the `src/` directory: * [`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`. 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/apply/`](src/apply/): Reconciles resources. Uses the generic reconciliation engine in `generic.rs` and stage-specific modules. Supports optional pruning/deletion of orphaned remote resources via the `--prune` flag. * [`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/init.rs`](src/init.rs): Scaffolds the initial `kaji.toml` / `.kaji.toml` configuration files. @@ -66,7 +66,7 @@ Multi-environment configurations are managed using the `--profile` (`-p`) flag: ## ⚙️ Project Configuration File (`kaji.toml` / `.kaji.toml`) -Project connection defaults and workspace parameters can be declared inside `kaji.toml` or `.kaji.toml` files in the current working directory. The configuration file is parsed at startup and merged with command-line inputs. +Project connection defaults, request timeouts, and workspace parameters can be declared inside `kaji.toml` or `.kaji.toml` files in the current working directory. The configuration file is parsed at startup and merged with command-line inputs. Settings are resolved in the following precedence order: 1. **CLI Flags** (highest) diff --git a/GEMINI.md b/GEMINI.md index eb1cf06..7160394 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -9,7 +9,7 @@ This document serves as the internal developer guide for `kaji`. It explains the 1. **Desired State**: Defined in local YAML files within the workspace. Support for **Environment Profiles & Overlays** allows for multi-environment configurations (e.g., `realm.yaml` + `realm.prod.yaml`). 2. **Current State**: Fetched from the Keycloak Admin API. 3. **Diff Engine (`src/plan/`)**: Compares the two states to identify what needs to be Created, Updated, or Deleted. It generates a `.kajiplan` file in the workspace containing the list of files that have pending changes. -4. **Reconciler (`src/apply/`)**: Executes the necessary API calls to bring the Current State in line with the Desired State. It uses **Dependency-Aware (Staged) Reconciliation** to ensure resources are applied in the correct order (e.g., Realms before Roles, Roles before Users). +4. **Reconciler (`src/apply/`)**: Executes the necessary API calls to bring the Current State in line with the Desired State. It uses **Dependency-Aware (Staged) Reconciliation** to ensure resources are applied in the correct order (e.g., Realms before Roles, Roles before Users). Supports optional pruning/deletion of orphaned remote resources not declared in the workspace configuration using the `--prune` flag (excluding protected system resources like default clients/roles). ### Core Modules @@ -67,7 +67,7 @@ For any resource `resource.yaml`, `kaji` looks for `resource.{profile}.yaml` and `kaji` supports project-level settings to override defaults and connection variables persistently. ### Architecture & Pipeline -1. **Schema Definition**: The `Config` struct is defined in [src/args.rs](src/args.rs). It represents optional fields for Keycloak connection credentials, vault parameters, and the workspace folder. +1. **Schema Definition**: The `Config` struct is defined in [src/args.rs](src/args.rs). It represents optional fields for Keycloak connection credentials, vault parameters, the workspace folder, and request timeouts. 2. **File Lookup**: In [src/lib.rs](src/lib.rs), `load_config_file` checks for: * A custom config path specified via `--config` CLI flag or `KAJI_CONFIG` env var. * `kaji.toml` in the current working directory. @@ -133,7 +133,7 @@ Located in `benches/`. Used to monitor performance for large workspaces with tho Secret handling is managed via the `SecretResolver` trait, which allows for multiple resolution strategies: - **EnvResolver**: Resolves `${VAR_NAME}` from the environment or a `.secrets` file. -- **VaultResolver**: Resolves `${vault:mount/path#field}` from a HashiCorp Vault KV2 engine. +- **VaultResolver**: Resolves `${vault:mount/path#field}` from a HashiCorp Vault KV2 engine. Utilizes a thread-safe in-memory cache (`tokio::sync::Mutex`) to avoid duplicate/redundant HTTP GET requests to Vault for the same secret path during planning/applying. - **CompositeResolver**: Chains multiple resolvers in a prioritized order. The masking heuristic during `inspect` looks for keys matching these patterns: diff --git a/README.md b/README.md index 3ad96b2..fc69616 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ server_url: "https://keycloak.prod.example.com" client_id: "kaji-cli" client_secret: "${PROD_KAJI_SECRET}" secrets_file: ".secrets.prod" # Load environment secrets from this file +timeout: 30 # Keycloak request timeout in seconds (optional) ``` ### 2. Use Overlays @@ -159,6 +160,7 @@ When running with `--profile prod`, `kaji` deep-merges the overlay onto the base | `KEYCLOAK_CLIENT_SECRET` | Client Secret (if using client credentials) | | | `VAULT_ADDR` | HashiCorp Vault URL | | | `VAULT_TOKEN` | HashiCorp Vault Token | | +| `KEYCLOAK_TIMEOUT` | Keycloak request timeout in seconds | `10` | ### Configuration File (`kaji.toml` / `.kaji.toml`) @@ -187,6 +189,9 @@ workspace = "kaji-workspace" # HashiCorp Vault Settings vault_addr = "http://vault:8200" vault_token = "my-vault-token" + +# Keycloak request timeout in seconds (optional) +timeout = 10 ``` #### Precedence / Priority Rules @@ -252,6 +257,9 @@ kaji apply --profile prod --yes # Review mode: confirm each change before application kaji apply --profile prod --review + +# Prune mode: delete remote resources that are not declared in local config files +kaji apply --profile prod --prune ``` ### `drift` diff --git a/benches/bench_authenticator_config.rs b/benches/bench_authenticator_config.rs index ba1b9a9..687e21d 100644 --- a/benches/bench_authenticator_config.rs +++ b/benches/bench_authenticator_config.rs @@ -87,12 +87,14 @@ fn bench_apply_auth_configs(c: &mut Criterion) { apply_authenticator_configs( &client, &workspace_dir, + Arc::new(workspace_dir.join(".secrets")), resolver.clone(), Arc::new(None), - "", + "test-realm", None, false, ui.clone(), + false, ) .await .unwrap(); diff --git a/docs/index.html b/docs/index.html index 8318c06..08ac3cd 100644 --- a/docs/index.html +++ b/docs/index.html @@ -156,7 +156,7 @@

Dependency-Aware Reconciliation

Profiles & TOML Config

-

Persist connection credentials, workspace paths, and target environments cleanly. Support for profiles, overlays, and project-wide configuration files.

+

Persist connection credentials, request timeouts, workspace paths, and target environments cleanly. Support for profiles, overlays, and project-wide configuration files.