{"id":28812745,"url":"https://github.com/integraal-klant-en-objectbeeld/iko","last_synced_at":"2026-02-17T11:16:18.560Z","repository":{"id":291956723,"uuid":"976488993","full_name":"Integraal-Klant-en-Objectbeeld/iko","owner":"Integraal-Klant-en-Objectbeeld","description":"Welcome at the IKO (Integraal Klant \u0026 Objectbeeld) repository.  ","archived":false,"fork":false,"pushed_at":"2026-01-21T16:20:59.000Z","size":22257,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-21T22:11:59.612Z","etag":null,"topics":["apache-camel","carbon-design-system","docker-compose","htmx","jq","oidc-provider","spring-mvc","thymeleaf-template-engine"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Integraal-Klant-en-Objectbeeld.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-02T07:39:56.000Z","updated_at":"2026-01-21T16:47:52.000Z","dependencies_parsed_at":"2025-05-28T15:22:50.853Z","dependency_job_id":"3a693af5-8448-4f2f-8cd7-2d8f5f17710c","html_url":"https://github.com/Integraal-Klant-en-Objectbeeld/iko","commit_stats":null,"previous_names":["integraal-klant-en-objectbeeld/iko"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/Integraal-Klant-en-Objectbeeld/iko","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integraal-Klant-en-Objectbeeld%2Fiko","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integraal-Klant-en-Objectbeeld%2Fiko/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integraal-Klant-en-Objectbeeld%2Fiko/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integraal-Klant-en-Objectbeeld%2Fiko/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Integraal-Klant-en-Objectbeeld","download_url":"https://codeload.github.com/Integraal-Klant-en-Objectbeeld/iko/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integraal-Klant-en-Objectbeeld%2Fiko/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28846737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apache-camel","carbon-design-system","docker-compose","htmx","jq","oidc-provider","spring-mvc","thymeleaf-template-engine"],"created_at":"2025-06-18T15:00:40.674Z","updated_at":"2026-02-17T11:16:18.547Z","avatar_url":"https://github.com/Integraal-Klant-en-Objectbeeld.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"iko-logo-wide.png\" alt=\"Iko Logo\"\u003e\n\n### Integraal Klant \u0026 Objectbeeld (IKO)\n\n![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)  \n\nIKO is a Kotlin/Spring Boot application that uses Apache Camel to integrate with external systems via connectors. It ships with an admin UI and a Docker-based local environment.\n\n---\n\n### Features\n- Spring Boot 3.5.x, Kotlin 2.2, JDK 21\n- OAuth2 (Keycloak) for admin login and JWT resource server\n- Redis caching for improved performance\n- Prometheus metrics endpoint for monitoring\n- Dockerfile for containerized runs and GitHub Actions CI/CD\n\n---\n\n### Prerequisites\n- Docker and Docker Compose\n- GitHub account (to use CI/CD workflows)\n- For local development: JDK 21 and Gradle wrapper\n\n---\n\n### Quick start with Docker\n1. Start the local stack:\n   ```bash\n   docker compose up -d\n   ```\n2. Add a hosts entry so Keycloak tokens use the hostname expected by configuration:\n   ```text\n   127.0.0.1 keycloak\n   ```\n3. Open the admin UI: `http://localhost:8080/admin`\n\nNotes:\n- The shipped `Dockerfile` (repo root) builds a runnable IKO container.\n- The compose file provides dependent services and sets up Keycloak for local login.\n\n---\n\n### Local development\n- Copy `.env.template` to `.env` and adjust values to your local setup.\n- For HTML live-refresh during local dev only, `.env.template` includes:\n  ```\n  SPRING_THYMELEAF_PREFIX=file:src/main/resources/templates/\n  # SPRING_WEB_RESOURCES_STATIC-LOCATIONS=file:src/main/resources/static/\n  ```\n  Remove or comment these when running inside Docker (the application defaults to classpath locations in `application.yml`).\n- Run the app via Gradle (env injected by the Dotenv Gradle plugin):\n  ```bash\n  ./gradlew bootRun\n  ```\n\n---\n\n### Configuration overview\n- Main config: `src/main/resources/application.yml`\n    - Disables OSIV (`spring.jpa.open-in-view=false`)\n    - Camel YAML routes path: `classpath:camel/*.yaml`\n    - Security: OAuth2/OIDC login for admin (roles claim + required admin roles configurable via `iko.security.admin.rolesClaim` / `iko.security.admin.authorities`) and JWT resource server for APIs (authorities from claim `resource_access.iko.roles`)\n\n---\n\n### Build and test\n- Run tests:\n  ```bash\n  ./gradlew test\n  ```\n- Build the application JAR:\n  ```bash\n  ./gradlew build\n  ```\n- Build a local Docker image:\n  ```bash\n  docker build -t iko:local .\n  ```\n\n---\n\n### Admin UI\n- URL: `http://localhost:8080/admin`\n- Tutorial (Aggregated Data Profile):\n  https://docs.integraal-klant-objectbeeld.nl/admin-configuratie/samengesteld-gegevensprofiel-aanmaken\n\n---\n\n### CI/CD\n\n#### Validate Build (`.github/workflows/validate-build.yml`)\n- Triggered on `pull_request` targeting the `main` branch.\n- Runs gradle build on the sources to make sure the sources build.\n- Is a requirement for merging a pull request to the `main` branch.\n  - Failing builds will not be allowed to merge.\n\n#### Snapshot workflow (`.github/workflows/snapshot-releases.yml`)\n- Triggered on `push` to the `main` branch or a manual `workflow_dispatch` against a chosen branch.\n- Builds the Docker image with Buildx (single-arch `linux/amd64`).\n- On `push` to `main`, pushes to GHCR (`ghcr.io/\u003cowner\u003e/\u003crepo\u003e`) with tags such as:\n    - `main` (default branch)\n    - `sha-\u003cshort\u003e`\n    - `snapshot-YYYYMMDDHHmm`\n    - `branch-\u003cname\u003e` for non-main branches\n- Adds OCI labels/annotations (title, description, revision, source, created).\n\n#### Manual release workflow (`.github/workflows/start-manual-release.yml`)\nThis workflow is used to cut a formal release that publishes a versioned container image and a GitHub Release.\n\n- Trigger: manually via the Actions tab (`workflow_dispatch`).\n- Input: `version` — a semantic version like `1.2.3` or `1.2.3-beta.1` (no leading `v`). The workflow validates this with a semver regex.\n- Permissions: `contents: write` (create GitHub Release) and `packages: write` (push to GHCR).\n\nHow it works (two-job pipeline):\n1. `build` job\n    - Checks out code, sets up QEMU and Buildx.\n    - Extracts Docker metadata for consistent OCI labels.\n    - Builds the Docker image once and exports it as a `docker`-format TAR (`iko-image.tar`) tagged locally as `iko:iko-\u003cepoch_seconds\u003e`.\n    - Uploads the TAR as a short-lived artifact.\n2. `push` job\n    - Downloads the image artifact and logs into GHCR with `GITHUB_TOKEN`.\n    - Loads the image from the TAR and retags it as:\n        - `ghcr.io/\u003cowner\u003e/\u003crepo\u003e:\u003cversion\u003e`\n        - `ghcr.io/\u003cowner\u003e/\u003crepo\u003e:latest`\n    - Pushes both tags.\n    - Creates a GitHub Release with tag `v\u003cversion\u003e` and autogenerated release notes. If the version contains a `-` (e.g., `-rc.1`), the release is marked as a prerelease.\n\nWhen to use it:\n- Use `start-manual-release.yml` when you are ready to publish a stable or pre-release version to consumers.\n- Use `snapshot-releases.yml` for continuous builds on `main` or for verifying PRs.\n\nHow to run a manual release:\n1. Go to GitHub → Actions → `Start release`.\n2. Click `Run workflow` and enter a semver (e.g., `1.3.0` or `1.3.0-rc.1`).\n3. Confirm to start. After completion you will have:\n    - GHCR images: `ghcr.io/\u003cowner\u003e/\u003crepo\u003e:\u003cversion\u003e` and `:latest`.\n    - GitHub Release: tag `v\u003cversion\u003e` with autogenerated notes.\n\nNotes and gotchas:\n- Architecture: currently builds for `linux/amd64` only. Adjust `platforms` if you need multi-arch.\n- Input version must be plain semver (e.g., `1.2.3`), not `v1.2.3`.\n- The artifact retention is short (1 day) to avoid stale reuse; the image is built once and then retagged/pushed in the separate job.\n\n---\n\n### More documentation\nYou can find more documentation [here](./doc/README.md)\n\n### Crypto\nIKO uses AES encryption for config storage of connectors. \nPlease generate a Base64 key in the env var IKO_CRYPTO_KEY via the .env file for local development.\n\nKotlin notebook code helps run pieces of code or just ask AI.\n```Kotlin\nfun generateBase64AesKey(keySize: Int = 256): String {\n    val keyGen = KeyGenerator.getInstance(\"AES\")\n    keyGen.init(keySize, SecureRandom())\n    val secretKey: SecretKey = keyGen.generateKey()\n    return Base64.getEncoder().encodeToString(secretKey.encoded)\n}\n\nfun main() {\n    val base64Key = generateBase64AesKey()\n    println(\"Generated AES key (Base64): $base64Key\")\n}\nmain()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintegraal-klant-en-objectbeeld%2Fiko","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fintegraal-klant-en-objectbeeld%2Fiko","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintegraal-klant-en-objectbeeld%2Fiko/lists"}