Skip to content

Feat: AIAC Event Broker + Keycloak SPI listener (phase 2, PR 2) - #753

Closed
oblinder wants to merge 385 commits into
rossoctl:mainfrom
s-and-p-team:aiac-phase2-event-broker
Closed

Feat: AIAC Event Broker + Keycloak SPI listener (phase 2, PR 2)#753
oblinder wants to merge 385 commits into
rossoctl:mainfrom
s-and-p-team:aiac-phase2-event-broker

Conversation

@oblinder

@oblinder oblinder commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #752 in the series toward #646 (AIAC phase 2 — platform
integration). This PR lands the Event Broker consumer and the Keycloak
SPI event-listener
— the plumbing for event-driven onboarding — as
implemented-but-inactive code. Nothing is wired live yet: the NATS broker
and the Keycloak SPI listener are both opt-in deployments, so with the default
manifests no events are produced or consumed. A later PR completes the live
Keycloak → Event Broker → AIAC Agent integration.

Stacked on #752 — do not merge first. #752 must merge before this one.
Its base is upstream main (the aiac-phase2-opa head branch lives on the
fork and can't serve as a PR base here), so until #752 lands this PR's diff
overlaps with it. Once #752 merges, this branch rebases onto main and the
diff collapses to just the changes below.

What's in this PR (delta on top of #752)

Event Broker — NATS JetStream consumer

  • aiac/src/aiac/agent/eventbus/consumer.py + stream.py: a durable
    aiac-agent-consumer queue-group consumer that mirrors the Controller's
    /apply/* HTTP routes — on each message it runs the same use-case handler +
    compute_and_apply sequence and awaits completion before acking.
  • Hardened connection handling: initial-connect retries with exponential
    backoff (broker down at boot is waited out, not crashed), indefinite
    reconnect, sync handlers offloaded via asyncio.to_thread under a lock to
    keep processing serial without blocking the loop.
  • DLQ semantics: on the 5th unacked delivery (max_deliver=5) the consumer
    republishes to aiac.apply.dlq and terminates the message (JetStream
    WorkQueue has no native dead-letter routing).
  • aiac/src/aiac/agent/init/wait_and_provision.py: init-time provisioning helper.
  • aiac/k8s/event-broker-deployment.yaml: NATS deployment (opt-in;
    imagePullPolicy: Never, side-loaded like the other AIAC manifests).

Keycloak SPI event-listener (Java) — Keycloak integration code, not yet wired

  • aiac/keycloak-spi/: a Keycloak EventListenerProviderFactory SPI that maps
    Keycloak events → the minimal {id} subject payload and best-effort-publishes
    to NATS (AiacEventListenerProvider, SubjectMapper, Dockerfile, Makefile,
    pom.xml, README) + SubjectMapperTest.
  • Installed into Keycloak only when you choose to build/deploy it — inert until then.

Docs & specs

  • aiac/docs/specs/components/keycloak-spi-listener.md — new component PRD
    (issue feat: Allow route based TARGET_AUDIENCE configuration #69): event→subject mapping, minimal payload, best-effort publish
    semantics, config, build/deploy, test seam.
  • event-broker.md, aiac-agent.md, PRD.md — DLQ corrected to
    consumer-republish, shipped consumer modules named, section wiring.
  • aiac/CLAUDE.md — external-reference update: the upstream dev guide moved
    from Kagenti to the Rosso Developer Guide
    (rossoctl/rossoctl/blob/main/docs/dev-guide.md).

Tests

  • aiac/test/agent/eventbus/ + aiac/test/agent/init/: dispatch routing,
    await-before-ack ordering, clean lifespan cancellation, connect-failure
    backoff, dotted-role subject routing.

Testing

  • .venv/bin/pytest test/ -m "not integration"492 passed (includes the
    new eventbus/init tests). Integration tests deselected (need a live cluster).
  • pre-commit run --files <delta> → all hooks pass on the changed files.

Pre-PR / dev-guide notes

  • Feature-flag gating: the Rosso Dev Guide asks for new features to be
    disabled by default. This feature is disabled by deployment — the consumer
    code runs in the Controller lifespan but has nothing to consume until the
    (opt-in) NATS broker and Keycloak SPI listener are deployed, which the default
    manifests do not do. The follow-up integration PR will wire it live.
  • DCO check (red — please disregard): the DCO check reports failure, but
    not because of a missing/invalid sign-off — every commit is properly
    signed. Its own summary says it "could not be evaluated because the complete
    pull request commit list could not be retrieved" (GitHub returned 250 commits
    from the REST API and the GraphQL fallback did not complete). This PR's range
    is ~378 commits only because it's stacked on the unmerged Feat: AIAC OPA plugin integration + live enforcement (phase 2, PR 1) #752 and carries
    its full history. Once Feat: AIAC OPA plugin integration + live enforcement (phase 2, PR 1) #752 merges and this rebases onto main, the count
    drops well under the 250-commit limit and DCO evaluates cleanly. No history
    rewrite is needed.

Related

Part of #646. Follow-up to #752.

Assisted-By: Claude (Anthropic AI) noreply@anthropic.com

anatolykoyfman and others added 30 commits June 26, 2026 15:09
Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
…odel

Split Policy Management Service into three components:
- Policy Store (aiac.policy.store): SQLite-backed CRUD service, K8s rename
  aiac-policy-store / aiac-policy-store-service:7074 / AIAC_POLICY_STORE_URL
- Policy Computation Engine (aiac.policy.computation): pure library module,
  compute_and_apply(rules) — IdP resolution, additive merge, PDP push
- Policy Model (aiac.policy.model): canonical, dependency-free Pydantic models
  with typed Role/Scope/Service fields and id-only hash/eq

New component PRDs:
  policy-store.md, policy-computation-engine.md, policy-model.md

Renamed library PRDs:
  library-policy-store.md (was library-state.md, AIAC_POLICY_STORE_URL)
  library-pdp-policy.md  (was library-pdp.md policy section, aiac.pdp.policy.library)

Updated in-place:
  library-idp.md — namespace aiac.idp.configuration, remove mappedScopes/get_roles
  scope-fetch, add get_services_by_role + get_services_by_scope
  PRD.md — component table, call flows, dependencies, arch decisions, deployment

Deleted deprecated:
  policy-management-service.md, library-state.md, library-pdp.md

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
… compute_and_apply(rules)

- Rename PolicyBuilderGraph → SharedApplyGraph; apply_policy → apply_rules
- Replace policy_model: PolicyModel | None state field with rules: list[PolicyRule]
- Remove TBD Policy sub-agent / Policy Builder sub-agent; shared apply node now
  delegates all Policy Store ↔ PDP Policy Writer coordination to PCE
- Add AIAC_POLICY_STORE_URL to config table; fix module paths to aiac.idp.configuration.api
- Remove apply_diff from individual sub-agent node lists (owned by shared apply)
- Update use cases note to reference policy-computation-engine.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…ion; remove mappedScopes; add PCE query methods

- Issue 1.11: move library to aiac/src/aiac/idp/configuration/, update all non-frozen import sites
- Issue 8.3: remove Role.mappedScopes, drop /scopes call in get_roles(), add get_services_by_role() and get_services_by_scope()
- Issue 8.4: unit tests for new methods and mappedScopes removal (260 tests pass)
- Fix show_keycloak_data.py: update imports and remove mappedScopes references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
- Add RAG Ingest → ChromaDB arrowhead in PRD.md high-level diagram
- Replace arch diagram in ARCHITECTURE-SUMMARY with PRD version (Policy Store
  Pod, Policy Compute Engn box, RAG Ingest ──► ChromaDB)
- Update component table: 7 → 8 entries; Policy Management Service →
  Policy Store (#3); add Policy Computation Engine (#4); update library
  module paths and descriptions throughout

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
… + PCE direct call

- Sub-agents now emit tuple[list[Role], list[Scope]] instead of list[PolicyRule]
- New shared Policy Rules Builder (agent/shared/policy_rules_builder/) converts
  tuple to list[PolicyRule]; Controller calls PCE directly with the rules
- Remove shared apply node (agent/shared/apply/)
- Remove UC2/UC3 Orchestrators; Controller dispatches directly to Build/Rebuild/Role sub-agents
- UC1 Orchestrator retained for two-step Service Provision pipeline
- Update top-level Mermaid diagram accordingly

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
Remove shared/apply/ section and all stale orchestrator framing.
Add policy_rules_builder/ TBD stub with Validate Node checks moved
into it. Update dispatch table, Controller responsibilities, Shared
Module diagram and BaseAgentState, File Structure tree, and Endpoints
table to reflect the new flow:

  sub-agent → tuple[list[Role], list[Scope]] → PRB → list[PolicyRule]
  → Controller → compute_and_apply(rules) (PCE)

Only UC1 (Service Onboarding) retains an Orchestrator; UC2/UC3 are
dispatched directly by the Controller.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…ract PRB to sub-PRD

- Remove Shared Module section: BaseAgentState, PDPSnapshot, ValidationVerdict,
  shared/nodes.py spec — all stale or incorrect
- Remove LLM Integration section
- Extract Policy Rules Builder full spec to aiac-agent/policy-rules-builder.md
  (nodes, PRBState, ValidationVerdict, Validate Node diagram, LLM integration stub)
- File tree: remove onboarding/policy/ subtree; rename propose_diff/validate_*
  nodes to propose_roles_scopes; drop AUDITOR_SYSTEM from sub-agent prompts.py
- Simplify shared/ to TBD stub pending PRB grill

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
- Remove individual files; keep folder structure only
- Group sub-agents under uc/ folder
- Rename roles/ -> role_update/ (flat, no sub-hierarchy)
- Replace shared/ with policy_rules_builder/

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
- Sub-agent output changed from tuple to list[tuple[list[Role], list[Scope]]]
- Controller now fans PRB over list, merges rules, makes single compute_and_apply call
- Mermaid diagram rewired: sub-agents → CTRL → PRB → CTRL → PCE (no direct sub-agent→PRB edges)
- CO subgraph adds Service Policy Update node (sequences provision → service_policy)
- Endpoints section: removed JSON response bodies; replaced with bare HTTP status paragraph
- Controller bullet points updated to describe fan-PRB-over-list flow
- Use Cases table: added Notes column with UC1 sequencing detail; footer note updated
- File structure tree: onboarding/ now shows orchestrator.py + service_policy/; annotations added
- Error Handling: appended bare-error propagation sentence
- PRB path updated: agent/shared/policy_rules_builder/ → agent/policy_rules_builder/

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
- UC1: two-stage Orchestrator (Service Provision LLM + Service Policy Update
  deterministic), aiac.idp.configuration.api throughout, replay-safety note,
  self-exclusion logic, tool/agent tuple packaging
- UC2: TBD stub with triggers and PRB→PCE pipeline stub; internal design deferred
- UC3: single deterministic path, one-element list[tuple], PRB picks relevance,
  PCE deletes stale rules

All diagrams: sub-agent → Controller → PRB → Controller → PCE (no sub-agent→PRB edge).
policy-rules-builder.md unchanged.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…olicy

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
- Structure: LangGraph StateGraph (graph internals TBD)
- Two entry points: build_role_rules(role, scopes) and build_scope_rules(roles, scope)
- PRB fetches its own ChromaDB context (both collections)
- No realm parameter, no trigger type in input state
- Error contract: raises on LLM/ChromaDB failure
- Dedup owned by PCE
- UC dispatch: UC3 -> build_role_rules, UC1 -> both (TBD), UC2 -> TBD

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…gents

Each sub-agent (UC1 Service Policy, UC2 Build, UC3 Role) now calls the
PRB directly, merges results internally, and returns list[PolicyRule] to
the Controller. The Controller's role shrinks to: dispatch → receive
list[PolicyRule] → call PCE. UC2 Rebuild delegates to Build.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
GET /services/{id}/roles and POST /services/{id}/roles/{role_id} use
the service account approach (get_client_service_account_user →
get_realm_roles_of_user / assign_realm_roles), not the client-scope
mapping API that the spec previously described.

GET /roles/{role_name}/scopes uses get_all_roles_of_client_scope +
realmMappings extraction, not get_realm_roles_of_client_scope.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…e tests and smoke test

- Add __hash__/__eq__ (id-only) to Role, Service, Scope in idp/configuration/models.py
- Remove set_service_type() and unused Literal import from idp/configuration/api.py
- Add TestHashAndEquality (15 tests) to test/pdp/library/test_models.py
- Replace TestSetServiceType with TestSetServiceTypeRemoved in test/pdp/library/test_configuration.py
- Add TestListServiceScopes and extend TestListServiceRoles in test/pdp/service/configuration/keycloak/test_main.py
- Add get_services_by_role/get_services_by_scope sections to smoke test show_keycloak_data.py

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
…o aiac

Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
- policy-model.md: add subject_roles dict[Subject, list[Role]] field;
  extend Subject hashability (__hash__/__eq__ by id); update usage
  example and testing decisions
- library-idp.md: add Subject to hashability set; add
  get_subjects_by_role(role) -> list[Subject] to Configuration class
- idp-configuration-service.md: add GET /subjects?role_id= filtered
  variant (role name resolution via get_realm_role_by_id, enriched
  subject list)
- policy-computation-engine.md: rewrite algorithm to 7 steps —
  composite role flattening, source_roles population (gap fix),
  subject_roles population, realm-level role semantics; update deps
  and testing decisions

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
- Add Subject.__hash__/__eq__ (id-only, type(self) guard)
- Add Configuration.get_subjects_by_role(role) to IdP library
- Add role_id query param to GET /subjects in IdP configuration service
- Restructure test/pdp/{library,service/configuration} -> test/idp/
  to mirror src/aiac/idp/ layout
- Update CLAUDE.md test command and smoke test path

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…y_role

- TestSubjectHashability: id-only hash/eq, cross-type inequality, dict key usage
- TestGetSubjectsByRole (library): happy path, empty list, non-2xx error, realm forwarded
- TestGetSubjectsByRole (service): 2-subject enrichment, empty members, 502 on each
  Keycloak phase error, enrichment shape, missing realm -> 422, unfiltered unchanged

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…yModel, PolicyModel

- Create aiac/src/aiac/policy/model/models.py with three Pydantic models
- Use field_serializer/field_validator for model-keyed dicts (source_roles,
  scope_targets, subject_roles) to work around Pydantic v2 unhashable-dict-key
  limitation during model_dump()/model_validate() round-trips
- All models use ConfigDict(extra='ignore')
- Add 19 unit tests covering construction, ValidationError, serialization,
  round-trip, hash/eq for all four IdP types, and extra-field suppression

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
…nit tests

- Add aiac.policy.store.service FastAPI service (port 7074)
- In-memory cache as serving layer; write-through to SQLite
- Endpoints: GET/POST/DELETE /policy and /policy/agents/{id}, GET /health
- 502 on SQLite write failure; 503 on health check failure
- AGENTPOLICY_DB_PATH defaults to /data/policy_model.db
- 18 unit tests using SQLite :memory: seam (all green)
- Update policy-store PRD to reflect policy_model.db filename

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
Implements aiac.policy.store.library (issue 8.7):
- aiac/src/aiac/policy/store/library/api.py with six module-level
  functions: get_policy, get_agent_policy, apply_policy,
  apply_agent_policy, delete_agent_policy, delete_policy
- Models imported from aiac.policy.model.models
- AIAC_POLICY_STORE_URL env var, default http://127.0.0.1:7074
- Non-2xx responses raise RuntimeError

Adds unit tests (issue 8.8):
- aiac/test/policy/store/library/test_api.py
- 13 tests covering success and error cases for all six functions
  plus URL fallback; all HTTP calls mocked

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
Signed-off-by: Anatoly Koyfman <anatoly@il.ibm.com>
…ter-service in PDP Policy Writer OPA spec

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

Signed-off-by: Oleg Blinder <olegb@il.ibm.com>
vz-ibm and others added 10 commits August 12, 2026 17:02
Reviewer OsherElhadad flagged three blocking issues (plus CodeQL alert rossoctl#179):

1. _patch_watsonx_for_reasoning_models was unconditional — it applied to
   every WatsonX deployment including the default mistral-large-2512, which
   supports response_format natively. That silently regressed structured
   output for existing users. Gate the patch behind a new
   SPARC_SCHEMA_IN_PROMPT=true setting (Settings.schema_in_prompt); the
   default path is now unchanged.

2. All three _patch_* helpers rebound methods on the shared ALTK class
   without a re-entry guard. ReflectionEngine caches components per track
   and lazily builds them, so a track switch would wrap the already-wrapped
   method — retry counts multiplied and debug lines duplicated on every
   subsequent call. Add _sparc_patched_reasoning / _sparc_patched_retry /
   _sparc_patched_debug sentinel attributes; each _patch_* no-ops if its
   sentinel is already set.

3. engine.reflect logged raw tool arguments at INFO. Args are
   caller-controlled — embedded newlines let a caller forge log lines
   (CodeQL alert rossoctl#179) — and can carry payloads (PII, payment ids, etc.).
   The same hunk had also dropped session_id/track from INFO. Restore
   session_id and track at INFO alongside tool/decision/score, and log args
   only at DEBUG when SPARC_LOG_REQUESTS=true.

Also addresses smaller items from the same review:

- tests/test_haiku_empty_response.py: replaced production PII in the
  conversation fixture (user id, names, DOBs, payment id, reservation ids)
  with synthetic values; gated both live-LLM probes behind pytest.skipif so
  they only run when RUN_HAIKU_TESTS=1 plus OAIKEY/OAIBASE are set (matches
  the reviewer's suggested opt-in path).
- tests/test_providers.py: added three deterministic unit tests — retry
  wrapper recovers after two ValueError empty-response failures, retry
  wrapper re-raises unrelated ValueErrors, and all three patches are
  idempotent under repeat application. No credentials or network required;
  fills in the coverage gap the reviewer noted for the retry and
  schema-injection wrappers.

Signed-off-by: Vitaly Zabershinsky <VITALYZ@il.ibm.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
…_ARG_KEYS

These two env vars were introduced by PR rossoctl#738 (merged 2026-08-10) but never
added to the sparc-service README's Configuration table. Documenting them here
so operators discover them without having to read settings.py.

Not touched here (not on main yet): SPARC_SKIP_TOOLS, SPARC_DEBUG_LLM, and
SPARC_SCHEMA_IN_PROMPT — those arrive with PR rossoctl#739, and will be documented in
a follow-up PR once that merges.

Signed-off-by: Vitaly Zabershinsky <VITALYZ@il.ibm.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Bumps [rojopolis/spellcheck-github-actions](https://github.com/rojopolis/spellcheck-github-actions) from 0.63.0 to 0.64.0.
- [Release notes](https://github.com/rojopolis/spellcheck-github-actions/releases)
- [Changelog](https://github.com/rojopolis/spellcheck-github-actions/blob/master/CHANGELOG.md)
- [Commits](rojopolis/spellcheck-github-actions@e619e00...26a39cd)

Signed-off-by: Oleg Blinder <oblinder@gmail.com>

---
updated-dependencies:
- dependency-name: rojopolis/spellcheck-github-actions
  dependency-version: 0.64.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.2.0 to 4.6.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](docker/login-action@650006c...dbcb813)

Signed-off-by: Oleg Blinder <oblinder@gmail.com>

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ssoctl#748)

* build(deps): Bump github/codeql-action/init from 4.37.4 to 4.37.6

Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.37.4 to 4.37.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@f205ea1...5595cca)

Signed-off-by: Oleg Blinder <oblinder@gmail.com>

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): Bump github/codeql-action from 4.37.4 to 4.37.6

Signed-off-by: Evaline Ju <69598118+evaline-ju@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Evaline Ju <69598118+evaline-ju@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evaline Ju <69598118+evaline-ju@users.noreply.github.com>
Bumps [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) from 4.37.0 to 4.37.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@99df26d...5595cca)

Signed-off-by: Oleg Blinder <oblinder@gmail.com>

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Address PR rossoctl#752 review feedback:
- opa-kind-enable.sh hardcoded the bundle_url namespace to
  rossoctl-system on both OPA legs, silently breaking the
  RELEASE_NAMESPACE override. Restore ${RELEASE_NAMESPACE} (the
  heredoc is unquoted, so it expands).
- Add an inline comment at the jwt.ParseInsecure call site noting
  the decoded subject is used for delegation provenance only, never
  for an auth decision.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
…client)

- opa-kind-driver.sh: guard mint_token's password==username grant with a
  DEV ONLY comment so it is not cargo-copied into staging/production.
- rego.py: emit a Rego comment before agent_role_scopes noting it is
  informational/debugging only and not referenced by allow.
- opa/requirements.txt: pin the kubernetes client to the tested major
  (>=36.0.3,<37) now that the writer mutates cluster state.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>

# Conflicts:
#	aiac/k8s/pdp-interface-deployment.yaml
#	aiac/src/aiac/pdp/service/policy/opa/rego.py
#	aiac/src/aiac/pdp/service/policy/opa/requirements.txt
Kagenti was renamed to Rosso; the upstream dev guide moved to
rossoctl/rossoctl/blob/main/docs/dev-guide.md. Update the AIAC
CLAUDE.md external-reference entry (name, URL) and note the
disabled-by-default ROSSOCTL_FEATURE_FLAG_<NAME> requirement.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 173 files, which is 73 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cd17cba7-c597-485a-babe-d4e9413d9897

📥 Commits

Reviewing files that changed from the base of the PR and between fa51661 and 79acd5e.

⛔ Files ignored due to path filters (3)
  • aiac/demo/agents/github_agent/uv.lock is excluded by !**/*.lock
  • aiac/uv.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (173)
  • .github/workflows/security-scans.yaml
  • aiac/CLAUDE.md
  • aiac/demo/agents/github_agent/.dockerignore
  • aiac/demo/agents/github_agent/.env.template
  • aiac/demo/agents/github_agent/Dockerfile
  • aiac/demo/agents/github_agent/README.md
  • aiac/demo/agents/github_agent/a2a_agent.py
  • aiac/demo/agents/github_agent/github_agent/__init__.py
  • aiac/demo/agents/github_agent/github_agent/agents.py
  • aiac/demo/agents/github_agent/github_agent/config.py
  • aiac/demo/agents/github_agent/github_agent/data_types.py
  • aiac/demo/agents/github_agent/github_agent/event.py
  • aiac/demo/agents/github_agent/github_agent/llm.py
  • aiac/demo/agents/github_agent/github_agent/main.py
  • aiac/demo/agents/github_agent/github_agent/prompts.py
  • aiac/demo/agents/github_agent/github_agent/tools.py
  • aiac/demo/agents/github_agent/k8s/configmaps.yaml
  • aiac/demo/agents/github_agent/k8s/github-agent-deployment.yaml
  • aiac/demo/agents/github_agent/pyproject.toml
  • aiac/demo/agents/github_agent/test/test_agent_card.py
  • aiac/demo/agents/github_agent/test/test_prereq.py
  • aiac/demo/agents/github_agent/test/test_tools.py
  • aiac/demo/agents/github_agent/test_startup.exp
  • aiac/demo/assets/INSTALL.md
  • aiac/demo/assets/agents/github_agent/README.md
  • aiac/demo/assets/agents/github_agent/k8s/configmaps.yaml
  • aiac/demo/assets/agents/github_agent/k8s/github-agent-deployment.yaml
  • aiac/demo/assets/install.sh
  • aiac/demo/assets/tools/github_tool/Dockerfile
  • aiac/demo/assets/tools/github_tool/k8s/github-tool-deployment.yaml
  • aiac/demo/tools/github_tool/Dockerfile
  • aiac/demo/tools/github_tool/k8s/github-tool-deployment.yaml
  • aiac/demo/tools/github_tool/pytest.ini
  • aiac/demo/tools/github_tool/requirements.txt
  • aiac/demo/tools/github_tool/server.py
  • aiac/demo/tools/github_tool/test/__init__.py
  • aiac/demo/tools/github_tool/test/conftest.py
  • aiac/demo/tools/github_tool/test/test_server.py
  • aiac/demo/use-cases/uc1-onboarding/Makefile
  • aiac/demo/use-cases/uc1-onboarding/demo.md
  • aiac/demo/use-cases/uc1-onboarding/init/00-discover-keycloak.sh
  • aiac/demo/use-cases/uc1-onboarding/init/01-prereqs.py
  • aiac/demo/use-cases/uc1-onboarding/init/02-clear.py
  • aiac/demo/use-cases/uc1-onboarding/init/03-setup.py
  • aiac/demo/use-cases/uc1-onboarding/lib/_lib.py
  • aiac/demo/use-cases/uc1-onboarding/lib/scenario.py
  • aiac/demo/use-cases/uc1-onboarding/lib/setup_keycloak.py
  • aiac/demo/use-cases/uc1-onboarding/onboard/04-onboard-agent.py
  • aiac/demo/use-cases/uc1-onboarding/onboard/05-onboard-tool.py
  • aiac/demo/use-cases/uc1-onboarding/show-state.py
  • aiac/docs/agents/domain.md
  • aiac/docs/agents/issue-tracker.md
  • aiac/docs/agents/triage-labels.md
  • aiac/docs/analysis/discover_mcp_services.py
  • aiac/docs/analysis/keycloak-access-control-analysis.md
  • aiac/docs/examples/opa-team1-policy.yaml
  • aiac/docs/specs/PRD.md
  • aiac/docs/specs/components/aiac-agent.md
  • aiac/docs/specs/components/aiac-agent/policy-rules-builder.md
  • aiac/docs/specs/components/aiac-agent/uc1-service-onboarding.md
  • aiac/docs/specs/components/event-broker.md
  • aiac/docs/specs/components/idp-configuration-service.md
  • aiac/docs/specs/components/keycloak-service.md
  • aiac/docs/specs/components/keycloak-spi-listener.md
  • aiac/docs/specs/components/library-idp.md
  • aiac/docs/specs/components/library-pdp-policy.md
  • aiac/docs/specs/components/library-policy-model-store.md
  • aiac/docs/specs/components/pdp-policy-keycloak-service.md
  • aiac/docs/specs/components/pdp-policy-writer-opa.md
  • aiac/docs/specs/components/policy-computation-engine.md
  • aiac/docs/specs/components/policy-guardrails-agent-policy-hygiene.md
  • aiac/docs/specs/components/policy-guardrails-agent.md
  • aiac/docs/specs/components/policy-model-store.md
  • aiac/docs/specs/components/policy-model.md
  • aiac/docs/specs/components/rag-ingest-service.md
  • aiac/docs/specs/components/rag-knowledge-base.md
  • aiac/docs/specs/demo/github-agent.md
  • aiac/docs/specs/demo/github-tool.md
  • aiac/docs/specs/integration-test/policy-pipeline.md
  • aiac/docs/specs/integration-test/uc1-onboarding-pipeline.md
  • aiac/k8s/agent-deployment.yaml
  • aiac/k8s/aiac-deployment-guide.md
  • aiac/k8s/event-broker-deployment.yaml
  • aiac/k8s/idp-configuration-keycloak-pod.yaml
  • aiac/k8s/opa-kind-driver.sh
  • aiac/k8s/opa-kind-enable.sh
  • aiac/k8s/opa-kind-restore.sh
  • aiac/k8s/opa-kind-runbook.md
  • aiac/k8s/pdp-interface-deployment.yaml
  • aiac/k8s/policy-model-store-statefulset.yaml
  • aiac/keycloak-spi/.dockerignore
  • aiac/keycloak-spi/.gitignore
  • aiac/keycloak-spi/Dockerfile
  • aiac/keycloak-spi/Makefile
  • aiac/keycloak-spi/README.md
  • aiac/keycloak-spi/pom.xml
  • aiac/keycloak-spi/src/main/java/io/aiac/keycloak/events/AiacEventListenerProvider.java
  • aiac/keycloak-spi/src/main/java/io/aiac/keycloak/events/AiacEventListenerProviderFactory.java
  • aiac/keycloak-spi/src/main/java/io/aiac/keycloak/events/SubjectMapper.java
  • aiac/keycloak-spi/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory
  • aiac/keycloak-spi/src/test/java/io/aiac/keycloak/events/SubjectMapperTest.java
  • aiac/pyproject.toml
  • aiac/src/aiac/agent/controller/Dockerfile
  • aiac/src/aiac/agent/controller/requirements.txt
  • aiac/src/aiac/agent/controller/routes.py
  • aiac/src/aiac/agent/eventbus/__init__.py
  • aiac/src/aiac/agent/eventbus/consumer.py
  • aiac/src/aiac/agent/eventbus/stream.py
  • aiac/src/aiac/agent/init/__init__.py
  • aiac/src/aiac/agent/init/wait_and_provision.py
  • aiac/src/aiac/agent/policy_rules_builder/graph.py
  • aiac/src/aiac/agent/uc/onboarding/provision/kube.py
  • aiac/src/aiac/agent/uc/onboarding/provision/nodes.py
  • aiac/src/aiac/idp/configuration/models.py
  • aiac/src/aiac/idp/service/configuration/keycloak/Dockerfile
  • aiac/src/aiac/pdp/service/policy/keycloak/Dockerfile
  • aiac/src/aiac/pdp/service/policy/keycloak/main.py
  • aiac/src/aiac/pdp/service/policy/keycloak/requirements.txt
  • aiac/src/aiac/pdp/service/policy/opa/Dockerfile
  • aiac/src/aiac/pdp/service/policy/opa/main.py
  • aiac/src/aiac/pdp/service/policy/opa/rego.py
  • aiac/src/aiac/pdp/service/policy/opa/requirements.txt
  • aiac/src/aiac/policy/computation/engine.py
  • aiac/src/aiac/policy/model_store/__init__.py
  • aiac/src/aiac/policy/model_store/keying.py
  • aiac/src/aiac/policy/model_store/library/__init__.py
  • aiac/src/aiac/policy/model_store/library/api.py
  • aiac/src/aiac/policy/model_store/service/Dockerfile
  • aiac/src/aiac/policy/model_store/service/__init__.py
  • aiac/src/aiac/policy/model_store/service/main.py
  • aiac/src/aiac/policy/model_store/service/requirements.txt
  • aiac/src/aiac/shared/upstream.py
  • aiac/test/agent/controller/test_routes.py
  • aiac/test/agent/eventbus/__init__.py
  • aiac/test/agent/eventbus/test_consumer.py
  • aiac/test/agent/eventbus/test_stream.py
  • aiac/test/agent/init/__init__.py
  • aiac/test/agent/init/test_wait_and_provision.py
  • aiac/test/agent/policy_rules_builder/test_graph.py
  • aiac/test/agent/policy_rules_builder/test_isolation.py
  • aiac/test/agent/uc/onboarding/provision/test_analyze_tool.py
  • aiac/test/agent/uc/onboarding/provision/test_classify_service.py
  • aiac/test/agent/uc/onboarding/provision/test_graph.py
  • aiac/test/idp/configuration/show_keycloak_data.py
  • aiac/test/idp/configuration/test_configuration.py
  • aiac/test/idp/configuration/test_models.py
  • aiac/test/idp/service/configuration/keycloak/test_main.py
  • aiac/test/integration/launcher.py
  • aiac/test/integration/probe.rego
  • aiac/test/integration/probe_uc1.rego
  • aiac/test/integration/scenario.py
  • aiac/test/integration/scenario_uc1.py
  • aiac/test/integration/test_launcher_select_live_pod.py
  • aiac/test/integration/test_policy_pipeline.py
  • aiac/test/integration/test_uc1_onboard_agent_only.py
  • aiac/test/integration/test_uc1_onboard_agent_then_tool.py
  • aiac/test/integration/test_uc1_onboard_tool_then_agent.py
  • aiac/test/integration/uc1_onboard.py
  • aiac/test/pdp/service/policy/keycloak/test_main.py
  • aiac/test/pdp/service/policy/opa/test_main.py
  • aiac/test/pdp/service/policy/opa/test_rego.py
  • aiac/test/policy/model_store/__init__.py
  • aiac/test/policy/model_store/library/__init__.py
  • aiac/test/policy/model_store/library/test_api.py
  • aiac/test/policy/model_store/service/__init__.py
  • aiac/test/policy/model_store/service/test_main.py
  • aiac/test/policy/model_store/test_keying.py
  • authbridge/authlib/plugins/opa/README.md
  • authbridge/authlib/plugins/opa/plugin.go
  • authbridge/authlib/plugins/opa/plugin_test.go
  • authbridge/authlib/plugins/tokenexchange/delegation_test.go
  • authbridge/authlib/plugins/tokenexchange/plugin.go
  • authbridge/demos/github-issue/k8s/github-tool-deployment.yaml

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Dependency Review flagged aiohttp 3.14.1 (transitive) in the demo
github-agent lockfile for GHSA-cq5v-8q36-5273 — a high-severity
out-of-bounds heap read in the C HTTP response parser (affected
<= 3.14.2, fixed in 3.14.3). Add an indirect floor pin (matching the
existing indirect-CVE-pin pattern) and regenerate uv.lock.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
@oblinder
oblinder marked this pull request as ready for review August 12, 2026 17:01
@oblinder
oblinder requested a review from a team as a code owner August 12, 2026 17:01
@oblinder
oblinder requested a review from abigailgold August 12, 2026 17:03
The Dependency Review CI check flagged cryptography 48.0.1 in the
github_agent demo lockfile for GHSA-g6cj-pr64-35w5 (CVE-2026-69247),
a PKCS#7 EnvelopedData Bleichenbacher oracle (high severity, affected
< 50.0.0). Raise the indirect pin from >=48.0.0,<49 to >=50.0.0 and
regenerate uv.lock (48.0.1 -> 50.0.0). No transitive dependency caps
cryptography below 50, so the resolve is clean.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Dependency Review flagged the provided-scope Keycloak server APIs in
aiac/keycloak-spi at 26.5.2 for four advisories:
  - GHSA-x4p7-7chp-64hq (high)  unauthorized auth via disabled SAML IdP
  - GHSA-q35r-vvhv-vx5h (mod)   UMA 2.0 permission-ticket info disclosure
  - GHSA-rr5q-3xwr-f323 (mod)   improper validation of specified quantity
  - GHSA-4q93-v92x-p89f (mod)   incorrect authorization

All four are fixed in 26.6.3. Raise the single keycloak.version property
(all four keycloak-* deps derive from it) from 26.5.2 to 26.6.3. These
deps are provided-scope (supplied by the Keycloak runtime, only jnats is
shaded into the provider jar), so this pins the compile-time API to a
patched line. Minor bump within 26.x against the stable
EventListenerProviderFactory SPI; the Java module is not built in this
repo's CI (only Dependency Review parses the pom).

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Dependency Review flagged the provided-scope Keycloak server APIs in
aiac/keycloak-spi. Split the remediation by whether a fix exists:

  Fixed by a version bump -> bump keycloak.version 26.5.2 -> 26.6.4
  (and align the Dockerfile KEYCLOAK_IMAGE base tag, previously still
  26.5.2, so the provider compiles against and runs on the same patched
  line). 26.6.4 clears GHSA-x4p7-7chp-64hq, GHSA-q35r-vvhv-vx5h,
  GHSA-rr5q-3xwr-f323, GHSA-4q93-v92x-p89f and GHSA-32h4-44jj-c5vx.

  No released fix -> allow-list in security-scans.yaml, mirroring the
  existing chromadb (GHSA-f4j7-r4q5-qw2c) precedent:
    GHSA-wcvj-vpvw-9rr5, GHSA-p3v8-fm5p-v84h, GHSA-q6h7-xxp7-7429
  These are Keycloak *server* advisories (affected <= 26.6.4, patched
  'None'); they are code we do not ship (only jnats is shaded into the
  provider jar) and are remediated operationally by patching the
  Keycloak deployment, so they cannot be closed by a dependency bump.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Dependency Review flagged cryptography 49.0.0 in aiac/uv.lock for
GHSA-g6cj-pr64-35w5 (CVE-2026-69247, PKCS#7 Bleichenbacher oracle,
high, affected < 50.0.0) once the github_agent lock was fixed. It is
an unconstrained transitive dependency, so 'uv lock --upgrade-package
cryptography' moves it 49.0.0 -> 50.0.0 with no other changes.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Move aiac/docs/opa-kind-runbook.md and scripts/opa-kind-{enable,restore,driver}.sh
into aiac/k8s/, and update every reference to their old locations across
CLAUDE.md, the runbook itself, and the integration test suite.

Signed-off-by: Oleg Blinder <oblinder@gmail.com>
admin_token() hardcodes the Keycloak master realm admin/admin credentials
with no caveat, unlike mint_token()'s existing DEV ONLY guard. Add the same
warning so the seeded Kind-cluster default is never cargo-copied into a
staging/production script.

Signed-off-by: Oleg Blinder <oblinder@gmail.com>
Signed-off-by: Oleg Blinder <oblinder@gmail.com>
@oblinder
oblinder marked this pull request as draft August 12, 2026 20:31
@oblinder

Copy link
Copy Markdown
Contributor Author

Superseded by #754, which carries the same Event Broker + Keycloak SPI work rebuilt on the aiac-phase2-opa branch (head aiac-phase2-opa-event-broker) so the delta over #752 is exactly the two event-broker commits. Closing this in favor of #754.

@oblinder oblinder closed this Aug 13, 2026
@github-project-automation github-project-automation Bot moved this from New/ToDo to Done in Rossoctl Issue Prioritization Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

6 participants