Skip to content

fix(rook): resolve block_on deadlock, fix dashboard route, add Docker e2e infra - #36

Merged
yacosta738 merged 13 commits into
mainfrom
feat/provider-architecture
May 31, 2026
Merged

fix(rook): resolve block_on deadlock, fix dashboard route, add Docker e2e infra#36
yacosta738 merged 13 commits into
mainfrom
feat/provider-architecture

Conversation

@yacosta738

Copy link
Copy Markdown
Contributor

Summary

4 commits resolving critical bugs and adding Docker e2e infrastructure:

Bug Fixes

  1. fix(rook): resolve block_on deadlock (apps/rook/src/di.rs, apps/rook/src/main.rs)

    • Handle::current().block_on() inside #[tokio::main] multi-thread runtime caused deadlock
    • Solution: Make RookContainer::build() async and use tokio::join!() for concurrent init tasks
    • Added OAuth credentials test 8.9 for ManageConnections::create
  2. fix(rook): dashboard wildcard route (apps/rook/src/dashboard.rs)

    • /*path is Axum 0.7 syntax; Axum 0.8.x panics at runtime with "Path segments must not start with `*`"
    • Fix: Change to {*path} (Axum 0.8 wildcard syntax)

Infrastructure

  1. feat(dev): Docker e2e infrastructure

    • Dockerfile.dev: Multi-stage ARM64 build (linux/arm64/v8) with Node.js 22 + pnpm
    • .dockerignore: Excludes node_modules, target/, dist/, .git/
    • dev/: Dockerfiles for Ubuntu/Alpine, docker-compose, e2e-test script
    • Dockerfile.dev.alpine: Alpine variant
    • Note: Use --network host when running on OrbStack (macOS)
  2. docs(openspec): archive dynamic-provider-registry

    • Archive report, updated ARCHITECTURE.md with Runtime Provider Registry section
    • Synced specs to openspec/specs/dynamic-provider-registry/
  3. feat(skills): shadcn-vue skill

    • New skill for shadcn/vue component guidance

Verification

  • cargo test --workspace --exclude dashboard: 189 tests passing
  • cargo clippy: clean
  • cargo fmt --check: clean
  • ✅ Server starts and responds on /health and / (Vue dashboard)
  • ✅ Docker image rook:e2e runs successfully on OrbStack

Running E2E Tests

# Build ARM64 image
docker buildx build --platform linux/arm64/v8 -t rook:e2e . -f Dockerfile.dev

# Run (use --network host on OrbStack)
docker run --rm --network host \
  -e ROOK_CONFIG=/app/rook.toml \
  -v /tmp/rook-data:/root/.local/share/cortex/rook \
  rook:e2e

- Make RookContainer::build() async and use tokio::join!() to run
  registry refresh and admin user init concurrently, avoiding
  Handle::current().block_on() deadlock in multi-thread runtime
- Fix dashboard wildcard route: /*path -> {*path} for Axum 0.8.x
- Add OAuth credentials test (8.9) for ManageConnections::create
- Dockerfile.dev: multi-stage build with Node.js 22 + pnpm for ARM64 (linux/arm64/v8)
- .dockerignore: exclude node_modules, target/, dist/, .git/
- dev/: Dockerfiles for Ubuntu/Alpine, docker-compose, e2e-test script
- Dockerfile.dev.alpine: Alpine-based variant
- dashboard/package-lock.json: npm lockfile for dashboard deps
…rchitecture

- Archive change dynamic-provider-registry with full verify-report, tasks, design
- Add Runtime Provider Registry section to ARCHITECTURE.md documenting the
  SQLite-backed dynamic registry pattern (FallbackRouter + ManageConnections)
- Sync delta specs to openspec/specs/dynamic-provider-registry/
@github-actions

Copy link
Copy Markdown

Thank you for contributing to this project with this PR, welcome to the community and the amazing world of open source!

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@yacosta738, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 37 minutes and 16 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 28c72ed8-0051-4dc2-83b3-77bbb1a8d2a3

📥 Commits

Reviewing files that changed from the base of the PR and between 8d482bf and d8d8b8d.

📒 Files selected for processing (6)
  • .github/workflows/ci.yml
  • Dockerfile.dev.alpine
  • dev/Dockerfile
  • dev/Dockerfile.runtime
  • dev/Dockerfile.ubuntu
  • openspec/changes/archive/2026-05-31-provider-connections/verify-report.md
📝 Walkthrough

Walkthrough

This PR delivers three major features plus extensive specification documentation: (1) comprehensive shadcn-vue developer skills covering CLI, component composition rules, theming, and MCP; (2) dynamic provider registry refactored from TOML to SQLite with async DI initialization, concurrent startup, and registry refresh on CRUD; (3) Docker/e2e infrastructure with multi-stage builds, Compose services, automated testing; plus PWA enhancements and specification archives for completed security authz and provider connections features.

Changes

Frontend Platform shadcn-vue Skills Documentation

Layer / File(s) Summary
shadcn-vue Skill Guide and CLI Reference
.agents/skills/frontend-platform/shadcn-vue/SKILL.md, cli.md
Introduces skill scope, CLI command patterns with package runner guidance, component selection mapping, and step-by-step workflows for installing/updating components and handling preset switching.
Component Composition, Forms, and Icon Rules
.agents/skills/frontend-platform/shadcn-vue/rules/composition.md, forms.md, icons.md
Prescriptive rules for correct component composition (group nesting, empty states, overlays), form/input structures with validation attributes, and icon usage patterns without sizing classes.
Styling Conventions, Customization, and MCP
.agents/skills/frontend-platform/shadcn-vue/customization.md, rules/styling.md, mcp.md
Theming via CSS variables and Tailwind; component customization via variants, class overrides, and wrapper composition; MCP server tool and registry configuration documentation.

Dynamic Provider Registry and DI Refactoring

Layer / File(s) Summary
Async DI Container and Concurrent Initialization
apps/rook/src/di.rs, apps/rook/src/main.rs
RookContainer::build becomes async; tokio::join! runs registry refresh and admin user creation concurrently; main awaits the build with error context.
Registry Refresh Logic and Test Coverage
crates/application/rook-usecases/src/manage_connections.rs
Adds refresh_registry() to rebuild providers from SQLite after CRUD; 900+ lines of unit tests cover credential handling, OAuth expiry, inactive skipping, decryption failures, partial build failure retention, and CRUD refresh triggers.
Dashboard Asset Route Update
apps/rook/src/dashboard.rs
Updates Axum catch-all route syntax from /*path to /{*path} for SPA asset serving.

Docker and Development Infrastructure

Layer / File(s) Summary
Docker Build Context and Multi-Stage Configurations
.dockerignore, Dockerfile.dev, Dockerfile.dev.alpine, dev/Dockerfile* (Ubuntu, Alpine, Runtime)
.dockerignore excludes nonessential files; five Dockerfiles provide multi-stage builder+runtime for Dev, Alpine, and Ubuntu bases with dependency caching and minimal runtime images.
Development Services, E2E Testing, and Configuration
dev/docker-compose.yml, dev/e2e-test.sh, dev/rook.toml, dev/test-configs/rook-minimal.toml, dev/README.md
Docker Compose defines Ubuntu and Alpine services with healthchecks; e2e test script automates container build/run/test cycles validating /health JSON and registry status; minimal TOML configs for dev/test.

Dashboard PWA Enhancements

Layer / File(s) Summary
Web App Manifest and Platform Icon Configuration
apps/rook/dashboard/index.html, apps/rook/dashboard/public/icons/manifest.json, public/icons/README.txt, public/icons/ios/Contents.json, public/icons/android/mipmap-anydpi-v26/ic_launcher.xml
PWA manifest defines app identity, display modes, theme colors, and 192px/512px icons; index.html references manifest and platform-specific meta tags; iOS and Android icon catalogs and adaptive icons.

Specification and Change Documentation

Layer / File(s) Summary
Architecture and Domain Documentation Updates
openspec/ARCHITECTURE.md, openspec/DOMAIN.md
ARCHITECTURE.md expands AuthTier/session/cookie tables and adds Runtime Provider Registry section; DOMAIN.md reformats value objects, ports, and use cases into consistent markdown tables.
Security/Authz Architecture Archive
openspec/changes/archive/2025-05-31-security-authz-architecture-notes/*
Completed phase documentation with spec, design, proposal, tasks, and verification confirming Phase 8 completion: 21 integration tests, session-based auth, CSRF, rate limiting, Argon2id password hashing.
Dynamic Provider Registry Archive and Specifications
openspec/changes/archive/2026-05-31-dynamic-provider-registry/*, openspec/specs/dynamic-provider-registry/*
Archive report with R8 deviation; design/spec documents defining SQLite-backed registry with Arc<RwLock<>> storage, atomic replace_all, partial-failure tolerance, and refresh-on-CRUD; verify report confirms PASS WITH WARNINGS (Phase 6 incomplete).
Provider Connections CRUD Archive and Specifications
openspec/changes/archive/2026-05-31-provider-connections/*, openspec/specs/provider-connections/*, openspec/specs/provider-connections-transport/*
Archive report and design/spec documents for persisted provider connection management with encrypted credentials, health checking, optimistic locking via expectedUpdatedAt, and feature-gated CRUD routes; verify report confirms PASS with non-critical warnings.
CI Workflow Updates
.github/workflows/ci.yml
SonarCloud job gated on secret presence; checkout keeps persist-credentials: false; action reference switched to master branch.

🎯 2 (Simple) | ⏱️ ~15 minutes

🐰 Hops through the docker forest with glee,
While rabbits refactor async DI,
New skills for the frontend, specs archived with care,
PWA icons bloom in the e2e air! 🚀✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/provider-architecture

@yacosta738 yacosta738 self-assigned this May 31, 2026
@yacosta738
yacosta738 requested a review from ryuknull May 31, 2026 11:14
- The commit SHA 9ab91c80e06747c8d9324b3b2d8aa442c6fb317c no longer exists (404)
- Use @master which always resolves to latest stable
- Add if: secrets.SONAR_TOKEN != '' to skip gracefully when token not configured
Comment thread dev/Dockerfile
Comment thread dev/Dockerfile
@github-actions github-actions Bot added the area/ci CI, tooling, and automation label May 31, 2026
Comment thread .github/workflows/ci.yml Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/application/rook-usecases/src/manage_connections.rs (1)

95-97: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't report CRUD failure after the SQLite write already committed.

create(), update(), and delete() now return the refresh_registry() error after the repository mutation succeeds. That makes the HTTP layer surface a failed write even though the row has already been created/updated/deleted, which is a retry hazard for these non-idempotent endpoints.

Either treat the refresh failure as post-commit recovery work and still return success, or introduce an explicit partial-success/compensation path. Returning a plain error here misrepresents the persisted state.

Also applies to: 147-151, 154-160

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/application/rook-usecases/src/manage_connections.rs` around lines 95 -
97, The repository mutation (self.repo.create / update / delete) already commits
before calling self.refresh_registry(), so do not propagate refresh_registry()
failure as the overall error; instead treat refresh_registry() as post-commit
recovery: catch or map its error, log or report a warning, and still return
success (e.g., Ok(conn) or Ok(())) so the HTTP layer reflects the persisted
change. Apply this change to the create/update/delete call sites in
manage_connections.rs where you currently call self.repo.*.await? followed by
self.refresh_registry().await? (including the other blocks referenced around
lines 147-151 and 154-160). Keep the repository result path unchanged and only
handle refresh_registry() errors non-fatally.
♻️ Duplicate comments (1)
openspec/changes/dynamic-provider-registry/spec.md (1)

79-79: ⚠️ Potential issue | 🟠 Major

Duplicate: Specification contradicts implementation (R8 deviation).

Same issue as in openspec/specs/dynamic-provider-registry/spec.md: Lines 79 and 612 state the registry is "always active" independent of provider_crud.enabled, but the implementation and verification report document that it IS gated behind this flag. The spec needs to be updated to match reality.

Also applies to: 612-612

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/dynamic-provider-registry/spec.md` at line 79, The spec
currently states the dynamic registry is "always active" independent of
provider_crud.enabled but implementation and verification gate it behind
provider_crud.enabled; update the specification text in both places that claim
"always active" so it matches reality by stating the dynamic registry is enabled
only when provider_crud.enabled is true (i.e., the dynamic registry is gated by
the provider_crud feature flag), and ensure any related wording for
provider_crud and the dynamic registry (references to provider_crud.enabled and
provider_crud) is consistent across the document.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.dockerignore:
- Around line 5-8: .dockerignore currently excludes target/, but dev/Dockerfile
expects target/debug/rook to be present (it runs COPY target/debug/rook
/usr/local/bin/rook), so remove target/ from .dockerignore (or specifically
allow target/debug/rook) so that the build context includes that binary; update
.dockerignore to stop ignoring target/ or add an explicit negation for
target/debug/rook so the COPY in dev/Dockerfile can succeed.

In `@apps/rook/src/di.rs`:
- Around line 120-121: The code currently treats refresh_result Err as a warning
and continues startup; instead, when refresh_registry() fails (refresh_result is
Err), log the error with tracing::error! and propagate the failure so the
process fails fast—e.g., return Err(e) (or use anyhow::bail!(e)) from the
enclosing function rather than tracing::warn!, ensuring startup aborts and
existing connections are not hidden; update the block that checks refresh_result
(and any caller expecting a Result) to propagate the error.

In `@crates/application/rook-usecases/src/manage_connections.rs`:
- Around line 1244-1300: The test update_preserves_credentials_when_not_provided
only checks the Credentials::ApiKey variant and should assert the actual
encrypted blob value to catch regressions in ManageConnections::update; change
the assertion to unwrap the Credentials::ApiKey payload and compare the api_key
string to "enc:v1:sk-original" (and in the related test that replaces keys
assert "enc:v1:sk-new-replacement"), locating the checks around the test
function update_preserves_credentials_when_not_provided and the similar test at
the other block, and ensure you validate the inner EncryptedBlob value rather
than using a wildcard match.
- Around line 2207-2224: The tests currently use MockRegistryWithProvider (and
EmptyRegistry) so refresh_registry() assertions don't depend on replace_all();
change the tests to use MockRegistry (not MockRegistryWithProvider or
EmptyRegistry), construct two connection entries where one builder/manager
deliberately fails and the other succeeds (e.g., keep SuccessProviderBuilder for
"openai-primary" and inject a failing builder or a FailDecryptKeyManager only
for the other connection), call
ManageConnections::new(...).refresh_registry().await.expect(...), then check
registry.get(...) to assert that only the successful provider was inserted by
replace_all(); also update the other two test blocks (the blocks around the
other ranges) the same way so partial-failure behavior is actually exercised.

In `@dev/Dockerfile.runtime`:
- Around line 18-20: The COPY uses a non-existent build stage name "builder"
(COPY --from=builder /app/target/debug/rook ...) so the image build will fail;
either add a multi-stage build stage named "builder" that compiles and outputs
/app/target/debug/rook (e.g., a FROM ... AS builder that builds the binary), or
change the --from value to the actual stage or image that contains the compiled
binary; update the Dockerfile.runtime accordingly so the referenced stage name
matches the one that produces /app/target/debug/rook.

In `@dev/Dockerfile.ubuntu`:
- Around line 21-39: The Dockerfile builds the binary in debug mode (RUN cargo
build --bin rook) but later tries to copy the release binary (COPY
--from=builder /app/target/release/rook ...) and uses an invalid “fallback” COPY
with shell redirection; fix by making the build produce a release binary and
removing the fallback: change RUN cargo build --bin rook to RUN cargo build
--bin rook --release, remove the erroneous fallback COPY line, and keep a single
COPY --from=builder /app/target/release/rook /usr/local/bin/rook (also ensure
the earlier build stage is named builder to match COPY --from=builder).
- Around line 15-22: The builder stage fails to include the workspace member and
uses invalid Dockerfile COPY fallback; update the build stage to copy the apps
directory (at least apps/rook and its Cargo.toml) into the build context so
cargo can find apps/rook, build the binary with cargo build --release (or run
cargo install --locked --path apps/rook if preferred), and in the runtime stage
remove the invalid COPY "fallback" logic and instead unambiguously COPY the
built release binary target/release/rook into the runtime image (or adjust to
copy the release path you produced), ensuring the runtime stage references the
same release artifact produced by the build stage (e.g., target/release/rook)
and not a debug-only build or shell-redirection hack.

In `@dev/e2e-test.sh`:
- Around line 85-87: `cmd_up()` is swallowing health-check failures in the
distro loop, so a container that never becomes healthy still lets `up`/`test`
continue. Update the `wait_healthy` call inside the `for distro in
"${DISTROS[@]}"` loop to propagate failures instead of forcing success, and
ensure the failure path aborts before printing the “Containers started…”
message. Use the existing `wait_healthy` and `cmd_up` flow to locate the change.

In `@Dockerfile.dev.alpine`:
- Around line 15-26: The Dockerfile currently copies Cargo.lock*, Cargo.toml,
rust-toolchain.toml and crates/ but omits the apps/ sources needed to build the
rook binary; before the RUN cargo build --bin rook step, add a COPY for the
application sources (either COPY apps/ ./apps/ or at minimum COPY apps/rook/
./apps/rook/) so that the rook crate (apps/rook/Cargo.toml and its src/) is
present when cargo builds the rook binary.

In `@openspec/ARCHITECTURE.md`:
- Line 135: Add an explicit "Implementation Note" or "Known Deviation" entry to
the dynamic-provider-registry specification that documents the R8 deviation
described in ARCHITECTURE.md: state that the registry is gated by the
configuration key provider_crud.enabled (which makes manage_connections None and
yields an empty registry when disabled) even though R8 expects the registry to
be "always active", and include the pragmatic justification already in
ARCHITECTURE.md so readers know this is an intentional, documented deviation.

In `@openspec/changes/archive/2026-05-31-dynamic-provider-registry/state.yaml`:
- Line 29: Update the inconsistent test count in the state record: replace the
current "Tests: 56 passed in rook-usecases, 5 passed in rook-core" entry with
the correct value that matches the other archive documents (change 56 to 73) so
the line reads "Tests: 73 passed in rook-usecases, 5 passed in rook-core";
locate the string in state.yaml (the "Tests:" entry for 2026-05-31) and make the
numeric correction.

In `@openspec/changes/archive/2026-05-31-dynamic-provider-registry/tasks.md`:
- Around line 73-79: The Phase 5 task checklist is inconsistent: tasks 5.6–5.12
are still unchecked but the verification and archive reports show those tests as
implemented and passing; update the checklist entries `5.6
refresh_registry_skips_inactive_connections`, `5.7
refresh_registry_decrypts_and_builds_provider`, `5.8
refresh_registry_partial_failure_keeps_valid_providers`, `5.9
refresh_registry_all_failures_results_in_empty_registry`, `5.10
create_calls_refresh_after_write`, `5.11 update_calls_refresh_after_write`, and
`5.12 delete_calls_refresh_after_write` in tasks.md to checked (change `[ ]` to
`[x]`) so the tasks list matches `verify-report.md` and `archive-report.md`;
after editing run a quick grep to confirm those test names appear as ✅ in the
verification files to ensure consistency.

In `@openspec/changes/dynamic-provider-registry/verify-report.md`:
- Line 6: The Verification Result currently reads "PASS WITH WARNINGS" while
WARNING `#1` flags that rule R8 (registry "always active") conflicts with the
implementation which gates activation behind provider_crud.enabled; update the
spec and verification state to eliminate this mismatch: either (A) update R8 in
the spec.md files to reflect the gating behavior (search for R8 and the phrase
"always active" and change wording to match provider_crud.enabled) then re-run
verification and mark as full "PASS", or (B) if you accept the divergence,
change the verification verdict string from "PASS WITH WARNINGS" to "CONDITIONAL
PASS - pending spec update" and add a clear note referencing R8 and
provider_crud.enabled documenting the approved divergence before archiving.

In `@openspec/specs/dynamic-provider-registry/spec.md`:
- Line 79: The spec claims the dynamic registry "is always active" independent
of provider_crud.enabled, but implementation (di.rs: manage_connections gated at
di.rs:54-76) and docs (ARCHITECTURE.md, verify-report.md R8) show it is
feature-gated; update spec.md to reflect reality by either adding an
"Implementation Notes" or "Deviations" section that documents the pragmatic
choice to gate the registry behind provider_crud.enabled (mention R8 and di.rs
manage_connections), or change R8's wording to state "The dynamic registry is
constructed when provider_crud.enabled = true" so the spec matches
ARCHITECTURE.md and the implementation.

---

Outside diff comments:
In `@crates/application/rook-usecases/src/manage_connections.rs`:
- Around line 95-97: The repository mutation (self.repo.create / update /
delete) already commits before calling self.refresh_registry(), so do not
propagate refresh_registry() failure as the overall error; instead treat
refresh_registry() as post-commit recovery: catch or map its error, log or
report a warning, and still return success (e.g., Ok(conn) or Ok(())) so the
HTTP layer reflects the persisted change. Apply this change to the
create/update/delete call sites in manage_connections.rs where you currently
call self.repo.*.await? followed by self.refresh_registry().await? (including
the other blocks referenced around lines 147-151 and 154-160). Keep the
repository result path unchanged and only handle refresh_registry() errors
non-fatally.

---

Duplicate comments:
In `@openspec/changes/dynamic-provider-registry/spec.md`:
- Line 79: The spec currently states the dynamic registry is "always active"
independent of provider_crud.enabled but implementation and verification gate it
behind provider_crud.enabled; update the specification text in both places that
claim "always active" so it matches reality by stating the dynamic registry is
enabled only when provider_crud.enabled is true (i.e., the dynamic registry is
gated by the provider_crud feature flag), and ensure any related wording for
provider_crud and the dynamic registry (references to provider_crud.enabled and
provider_crud) is consistent across the document.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 193b3575-bc26-4ae9-a1c8-cb038c48031e

📥 Commits

Reviewing files that changed from the base of the PR and between 4b07441 and d8f4343.

⛔ Files ignored due to path filters (2)
  • apps/rook/dashboard/package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (36)
  • .agents/skills/frontend-platform/shadcn-vue/SKILL.md
  • .agents/skills/frontend-platform/shadcn-vue/cli.md
  • .agents/skills/frontend-platform/shadcn-vue/customization.md
  • .agents/skills/frontend-platform/shadcn-vue/mcp.md
  • .agents/skills/frontend-platform/shadcn-vue/rules/composition.md
  • .agents/skills/frontend-platform/shadcn-vue/rules/forms.md
  • .agents/skills/frontend-platform/shadcn-vue/rules/icons.md
  • .agents/skills/frontend-platform/shadcn-vue/rules/styling.md
  • .dockerignore
  • Dockerfile.dev
  • Dockerfile.dev.alpine
  • apps/rook/src/dashboard.rs
  • apps/rook/src/di.rs
  • apps/rook/src/main.rs
  • crates/application/rook-usecases/src/manage_connections.rs
  • dev/Dockerfile
  • dev/Dockerfile.alpine
  • dev/Dockerfile.runtime
  • dev/Dockerfile.ubuntu
  • dev/README.md
  • dev/docker-compose.yml
  • dev/e2e-test.sh
  • dev/rook.toml
  • dev/test-configs/rook-minimal.toml
  • openspec/ARCHITECTURE.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/archive-report.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/state.yaml
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/tasks.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/verify-report.md
  • openspec/changes/dynamic-provider-registry/design.md
  • openspec/changes/dynamic-provider-registry/spec.md
  • openspec/changes/dynamic-provider-registry/state.yaml
  • openspec/changes/dynamic-provider-registry/tasks.md
  • openspec/changes/dynamic-provider-registry/verify-report.md
  • openspec/specs/dynamic-provider-registry/design.md
  • openspec/specs/dynamic-provider-registry/spec.md

Comment thread .dockerignore
Comment thread apps/rook/src/di.rs
Comment thread crates/application/rook-usecases/src/manage_connections.rs
Comment thread crates/application/rook-usecases/src/manage_connections.rs
Comment thread dev/Dockerfile.runtime Outdated
Comment thread openspec/ARCHITECTURE.md
Comment thread openspec/changes/dynamic-provider-registry/verify-report.md Outdated
Comment thread openspec/specs/dynamic-provider-registry/spec.md
…eports

Add proposal, design, tasks, verification report, state, and archive report for the provider-connections change. Documents the full SDD lifecycle, including domain model, repository port, encryption, API design, config, and test coverage. Marks all phases as complete and verified.
Dockerfile fixes:
- .dockerignore: allow !target/debug/rook for dev/Dockerfile workflow
- Dockerfile.dev.alpine: add missing COPY apps/ ./apps/, use release build
- dev/Dockerfile.ubuntu: fix missing apps COPY, debug→release build,
  remove invalid fallback COPY syntax
- dev/Dockerfile.runtime: rewrite as proper multi-stage build with builder
  stage (was referencing non-existent 'builder' stage)

Security hardening (Semgrep):
- Add USER non-root to all runtime Dockerfiles:
  Dockerfile.dev, dev/Dockerfile, dev/Dockerfile.ubuntu,
  dev/Dockerfile.runtime, Dockerfile.dev.alpine

Also fix copy-paste comment typo in Dockerfile.dev (debug→release)
…y-authz-architecture-notes changes

- Update `state.yaml` to archive `provider-connections` (phase: sdd-archive, archived: true, archive_date: 2026-05-31)
- Add archive state for `security-authz-architecture-notes` (archived: true, archived_at: 2025-05-31)
- Add `apply-progress.md` and `verification_summary.md` for security-authz-architecture-notes (phase 8 complete, all specs verified)
- Update `archive-report.md` for provider-connections with artifact and verification tables
- Normalize and align markdown tables in `design.md`, `tasks.md`, `proposal.md`, `ARCHITECTURE.md`, `DOMAIN.md`, and `spec.md` for consistency
@github-actions github-actions Bot added the area/docs Documentation and README label May 31, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
apps/rook/dashboard/public/icons/README.txt (1)

1-19: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align README icon paths with actual implementation paths.

The examples here still point to root-level assets (/favicon.ico, /icon-192.png, etc.), but this PR serves icons under /icons/.... Copy/pasting this README will produce broken references.

Suggested doc patch
-    <link rel="icon" href="/favicon.ico" sizes="any">
-    <link rel="apple-touch-icon" href="/apple-touch-icon.png">
+    <link rel="icon" href="/icons/favicon.ico" sizes="any">
+    <link rel="apple-touch-icon" href="/icons/ios/AppIcon~ios-marketing.png">

@@
-        { "src": "/favicon.ico", "type": "image/x-icon", "sizes": "16x16 32x32" },
-        { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
-        { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" },
-        { "src": "/icon-192-maskable.png", "type": "image/png", "sizes": "192x192", "purpose": "maskable" },
-        { "src": "/icon-512-maskable.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" }
+        { "src": "/icons/favicon.ico", "type": "image/x-icon", "sizes": "16x16 32x32" },
+        { "src": "/icons/icon-192.png", "type": "image/png", "sizes": "192x192" },
+        { "src": "/icons/icon-512.png", "type": "image/png", "sizes": "512x512" },
+        { "src": "/icons/icon-192-maskable.png", "type": "image/png", "sizes": "192x192", "purpose": "maskable" },
+        { "src": "/icons/icon-512-maskable.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/rook/dashboard/public/icons/README.txt` around lines 1 - 19, Update the
README examples so the icon paths match the app's served location (/icons/...),
not root-level assets; replace occurrences of "/favicon.ico",
"/apple-touch-icon.png", "/icon-192.png", "/icon-512.png",
"/icon-192-maskable.png", and "/icon-512-maskable.png" in the HTML <head>
snippet and the manifest "icons" array with their corresponding "/icons/..."
counterparts used by the implementation so copy/pasted snippets point to valid
assets.
openspec/specs/provider-connections/spec.md (1)

476-484: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Active spec config contract does not match implementation.

The spec requires provider_crud.db_path, but verification notes in this PR indicate runtime uses database.db_path and ProviderCrudConfig lacks db_path. This should be corrected in the active spec (or explicitly marked as deferred) to prevent incorrect deployments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/specs/provider-connections/spec.md` around lines 476 - 484, The spec
declares provider_crud.db_path but the implementation reads database.db_path and
ProviderCrudConfig does not expose db_path; reconcile them by either updating
the spec to document database.db_path as the source of truth or changing the
code to add db_path to ProviderCrudConfig and make the runtime read
provider_crud.db_path (and validate it when provider_crud.enabled is true
alongside ENCRYPTION_PASSPHRASE/ENCRYPTION_SALT); update any config
validation/verification logic and docs so the config key, the ProviderCrudConfig
type, and the runtime lookup all consistently reference the same symbol
(provider_crud.db_path or database.db_path).
openspec/specs/provider-connections-transport/spec.md (1)

13-13: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Cross-spec reference is ambiguous/stale.

This points to provider-connections.md, but the provided canonical spec is openspec/specs/provider-connections/spec.md. Use the explicit path to avoid broken navigation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/specs/provider-connections-transport/spec.md` at line 13, Update the
ambiguous cross-spec reference in the sentence that points to
`provider-connections.md` so it uses the explicit canonical path
`openspec/specs/provider-connections/spec.md`; locate the line containing
"provider-connections.md" in `spec.md` and replace it with the full path
`openspec/specs/provider-connections/spec.md` to ensure correct navigation and
avoid stale/ambiguous links.
openspec/changes/archive/2025-05-31-security-authz-architecture-notes/proposal.md (1)

124-127: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

CSRF flow cannot work as written with HttpOnly token cookie.

The flow requires client-side echo of cookie value into X-CSRF-Token, but HttpOnly blocks client access. Update the proposal to use a readable CSRF cookie (non-HttpOnly) or a different CSRF token transport model.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/proposal.md`
around lines 124 - 127, The proposal's CSRF double-submit flow is inconsistent
because the step "Set-Cookie: csrf_token (HttpOnly, Secure)" prevents the client
from reading the cookie to echo it in the "X-CSRF-Token" header; update the
proposal to either set the csrf_token cookie as readable (remove HttpOnly) so
the client can read and echo it in the POST flow ("Client → POST /api/...
(cookie + X-CSRF-Token header)" and "Validate X-CSRF-Token == csrf_token
cookie"), or replace the double-submit model with a synchronizer token (issue
token in GET /login response body and validate against server-side session) or
another transport (e.g., store token in a JavaScript-accessible storage and use
SameSite/secure cookie only for session) and explicitly call out the chosen
change in the documented flow.
Dockerfile.dev (1)

48-57: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Create the runtime account before switching users.

USER non-root points to a username that this image never creates. Docker uses the USER value for the runtime ENTRYPOINT/CMD, and when a username is supplied it must exist in the container, so this image will not start as written. (docs.docker.com)

Proposed fix
 # Copy binary from builder (release build)
 COPY --from=builder /app/target/release/rook /usr/local/bin/rook

 # Copy test config
 COPY dev/test-configs/rook-minimal.toml /app/rook.toml
+
+RUN groupadd --system rook \
+    && useradd --system --gid rook --home-dir /app --no-create-home rook \
+    && chown -R rook:rook /app

 # Expose default port
 EXPOSE 8080

-USER non-root
+USER rook
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile.dev` around lines 48 - 57, The Dockerfile sets USER non-root but
never creates that account, so container startup will fail; modify the
Dockerfile to create the runtime user and group before the USER non-root
instruction (e.g. add commands that create a group and user like
addgroup/useradd or use groupadd/useradd with a stable UID/GID), ensure
ownership of /usr/local/bin/rook and /app/rook.toml is adjusted (chown) so the
non-root user can access them, then keep the existing USER non-root line;
reference the existing USER non-root and the copied files (/usr/local/bin/rook
and /app/rook.toml) when adding the creation and chown steps.
♻️ Duplicate comments (2)
openspec/specs/dynamic-provider-registry/spec.md (1)

79-80: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Resolve R8 contradiction with implemented feature-gate behavior.

The spec still says the registry is “always active,” but your architecture/archive verification docs explicitly state it is gated by provider_crud.enabled. Please align R8 and section 3.2 with the documented implemented behavior (or add a formal deviation note in this spec section).

Also applies to: 611-614

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/specs/dynamic-provider-registry/spec.md` around lines 79 - 80,
Update the spec to resolve the contradiction: change the R8/section 3.2 language
that claims the dynamic registry is "always active" to state that the dynamic
registry's CRUD HTTP routes are gated by the feature flag provider_crud.enabled
(matching your architecture/archive docs), or alternatively add an explicit
"Deviation" note in R8 and 3.2 that documents the implemented behavior and
rationale; reference R8, section 3.2, and the provider_crud.enabled flag in the
updated text so readers can reconcile the behavior with the implementation.
openspec/changes/archive/2026-05-31-dynamic-provider-registry/tasks.md (1)

73-79: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Sync Phase 5 checklist with verification artifacts.

Tasks 5.6–5.12 are still unchecked here, but the verification docs in this PR report those tests as implemented and passing. Update these checklist items to [x] so tasks.md matches the archived verification state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/archive/2026-05-31-dynamic-provider-registry/tasks.md`
around lines 73 - 79, Update the Sync Phase 5 checklist by marking items 5.6
through 5.12 as completed (change their list markers from [ ] to [x]) so the
tasks.md checklist matches the archived verification state reported by the PR;
specifically edit the lines for "5.6 Add
`refresh_registry_skips_inactive_connections`", "5.7 Add
`refresh_registry_decrypts_and_builds_provider`", "5.8 Add
`refresh_registry_partial_failure_keeps_valid_providers`", "5.9 Add
`refresh_registry_all_failures_results_in_empty_registry`", "5.10 Add
`create_calls_refresh_after_write`", "5.11 Add
`update_calls_refresh_after_write`", and "5.12 Add
`delete_calls_refresh_after_write`" to be checked.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 186: Replace the invalid job-level condition that references secrets by
exposing the secret as an env var and checking that env var (set workflow or job
env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}) and change jobs.sonar.if to use
if: env.SONAR_TOKEN != '' so the job-level condition uses env instead of secrets
(refer to jobs.sonar.if and env.SONAR_TOKEN); also pin the
sonarsource/sonarcloud-action@master reference to a specific commit SHA (replace
sonarsource/sonarcloud-action@master with
sonarsource/sonarcloud-action@<commit-sha>) to avoid using an unpinned action.

In `@dev/Dockerfile`:
- Line 33: The Dockerfile currently switches to a non-existent user via the
instruction "USER non-root"; create the runtime account before switching by
adding steps to create the user and group (e.g., adduser/useradd or groupadd),
create its home directory, set ownership of any app directories (chown), and
then set USER non-root so the container runs as that account; locate the
Dockerfile section around the "USER non-root" token and insert the user creation
and chown commands immediately before that USER instruction and ensure the
created username matches "non-root".

In `@dev/Dockerfile.runtime`:
- Around line 41-46: The runtime Dockerfile sets USER non-root but never creates
that account; add steps before the USER non-root line to create the non-root
account and group (e.g., using adduser/useradd or addgroup + adduser), create
its home directory, chown any runtime-owned files/directories (like /app and
/usr/local/bin/rook) to that user, and set any needed HOME/UID/GID environment
vars so USER non-root references a real user; update the runtime stage around
the COPY lines and before USER non-root to perform these actions.

In `@dev/Dockerfile.ubuntu`:
- Around line 37-46: The Dockerfile ends with "USER non-root" but never creates
that account, causing container startup failures; modify the Dockerfile to
create a non-root runtime user and group before the "USER non-root" line (e.g.,
use groupadd/useradd or addgroup/adduser), chown any runtime-owned paths (like
/usr/local/bin/rook and /app or /app/rook.toml created by the COPY lines), and
then switch to "USER non-root"; ensure the user creation command and chown occur
after the COPY --from=builder /app/target/release/rook ... and COPY
dev/test-configs/rook-minimal.toml ... steps and before the final USER non-root
instruction so the named user actually exists at runtime.

In `@Dockerfile.dev.alpine`:
- Around line 38-46: The Dockerfile switches to USER non-root but never creates
that account, causing the container to fail to start; before the line that sets
"USER non-root" create the runtime account/group (e.g., add a non-root user and
group) and chown the installed binary (/usr/local/bin/rook) and config
(/app/rook.toml) to that user so runtime permissions are correct; ensure the
created username matches the USER directive ("non-root") and use the same
UID/GID/paths referenced in the COPY lines and EXPOSE 8080 so the switch to USER
non-root succeeds.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/apply-progress.md`:
- Around line 51-53: Update the absolute completion claims to acknowledge the
recorded open deviations: replace the sentence "All 71 specs (SPEC-001 through
SPEC-071) verified as ✅ IMPLEMENTED in `verification_summary.md`." with a
qualified statement such as "All 71 specs (SPEC-001 through SPEC-071) verified
with known deviations — see verification_summary.md for details," and change the
heading "## Phase 8 Status: ✅ COMPLETE" to a qualified status like "## Phase 8
Status: PASS WITH KNOWN DEVIATIONS" so the document aligns with the unresolved
gaps documented in the lines referencing deviations (lines 43–47).

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/design.md`:
- Around line 318-320: The design currently requires a double-submit CSRF token
but marks the cookie `csrf_token` as HttpOnly, which prevents client-side JS
from reading and sending it in the `X-CSRF-Token` header; fix by choosing one of
two options and updating the design and table: either make `csrf_token`
non-HttpOnly (set HttpOnly=false in the table and document that dashboard/client
JS reads the cookie and sends `X-CSRF-Token`) or switch to a
server-issued/header-token pattern (remove double-submit, describe a
server-generated token delivered in a non-cookie header or via an authenticated
endpoint and validated on each request), and update the `csrf_token` handling in
the design text (references to double-submit, `csrf_token`, `HttpOnly`, and
`X-CSRF-Token`) to match the chosen approach.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/spec.md`:
- Around line 429-435: The spec is inconsistent: SPEC-060 mandates an HttpOnly
cookie named csrf_token while SPEC-061 requires browser clients to read and copy
that token into the X-CSRF-Token header; choose one fix: either update SPEC-060
to make csrf_token non-HttpOnly (allowing JS to read it) and note
SameSite/Secure constraints, or update SPEC-061 to accept the cookie being sent
automatically (double-submit-cookie alternative) or require an alternative
non-HttpOnly token carrier (e.g., a separate public cookie or hidden form field)
and remove the requirement that browsers copy csrf_token into X-CSRF-Token;
apply the same change consistently for the other occurrence referenced as well.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/tasks.md`:
- Line 436: Fix the typo in the task list item that reads "Test expired session
returns401" by adding a space so it reads "Test expired session returns 401";
locate the list under the tasks section (the numbered item "4.") in the document
and update the text for clarity.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/verification_summary.md`:
- Line 27: The verification summary claims Argon2id was implemented with "1
parallelism" but SPEC-010 requires parallelism ≥4; update the actual
implementation in encryption-inmemory/src/password.rs by changing the
Argon2idHasher parameters to use parallelism >=4 (keep OWASP memory and
iterations), or if you cannot change the implementation now, update
verification_summary.md to mark SPEC-010 as not fully implemented and correct
the parameter detail; reference the Argon2idHasher symbol when making the change
so the evidence and code stay consistent.
- Around line 75-76: The verification summary incorrectly marks SPEC-070 and
SPEC-071 as fully implemented despite per-key enforcement being deferred; update
the SPEC-070 and SPEC-071 rows to reflect partial compliance (e.g., "PARTIALLY
IMPLEMENTED" or "DEFERRED - SERVER-WIDE ONLY") and amend the top-line summary
"All 71 specs verified" to the correct partial count and wording; also add a
brief note next to the SPEC-070/SPEC-071 entries (or in the notes section)
stating that the implementation in
transport-axum/src/middleware/api_key_rate_limiter.rs currently provides per-key
buckets configuration but per-key enforcement is not active and therefore
rate-limiting is partially implemented.
- Line 61: Update the spacing typos in verification_summary.md by replacing any
run-together tokens: change "Returns429" to "Returns 429" for the SPEC-051 row
(and any other rows like the one at line ~130) and change "Phase8 Status" to
"Phase 8 Status" where present so the table reads "Returns 429" and "Phase 8
Status" consistently (search for SPEC-051 and the string "Phase8" to locate
occurrences).

In
`@openspec/changes/archive/2026-05-31-dynamic-provider-registry/verify-report.md`:
- Around line 153-154: Update the verdict summary bullets in the verify report
to accurately reflect the R8 deviation: change any statements that claim full
compliance for R1–R8 to "implemented, with documented R8 deviation" (or similar
wording) and call out the specific deviation about gating the dynamic registry
behind provider_crud.enabled which causes manage_connections to be None when
disabled; ensure the same rewording is applied to the duplicate section around
lines 170–174 so the report consistently states "implemented with documented R8
deviation" rather than full compliance.

In `@openspec/changes/archive/2026-05-31-provider-connections/design.md`:
- Around line 352-364: The design doc currently lists ProviderCrudConfig.db_path
but the implementation uses DatabaseConfig.db_path and ProviderCrudConfig only
contains enabled; update the archived text to match the verified implementation
by removing db_path from ProviderCrudConfig and moving the db_path setting into
the DatabaseConfig section (and update the default TOML accordingly), or
alternatively add a short “planned vs implemented” note that explicitly states
ProviderCrudConfig only has enabled while DatabaseConfig.db_path is used in
production; reference ProviderCrudConfig.enabled, ProviderCrudConfig.db_path,
and DatabaseConfig.db_path when making the change.
- Line 7: The line in
openspec/changes/archive/2026-05-31-provider-connections/design.md currently
points to the stale string "openspec/changes/provider-connections/spec.md";
locate the actual canonical spec file for provider-connections in the repository
(the true spec path) and replace that stale reference with the correct
path/filename and a working markdown link, ensuring the referenced file exists
and the link is not broken.

In `@openspec/changes/archive/2026-05-31-provider-connections/verify-report.md`:
- Around line 146-147: The archived verify-report references the wrong artifact
path; update the artifact link in
openspec/changes/archive/2026-05-31-provider-connections/verify-report.md so it
points to the archived location instead of the non-archive one (replace
occurrences of "openspec/changes/provider-connections/verify-report.md" with
"openspec/changes/archive/2026-05-31-provider-connections/verify-report.md" to
restore correct traceability).

---

Outside diff comments:
In `@apps/rook/dashboard/public/icons/README.txt`:
- Around line 1-19: Update the README examples so the icon paths match the app's
served location (/icons/...), not root-level assets; replace occurrences of
"/favicon.ico", "/apple-touch-icon.png", "/icon-192.png", "/icon-512.png",
"/icon-192-maskable.png", and "/icon-512-maskable.png" in the HTML <head>
snippet and the manifest "icons" array with their corresponding "/icons/..."
counterparts used by the implementation so copy/pasted snippets point to valid
assets.

In `@Dockerfile.dev`:
- Around line 48-57: The Dockerfile sets USER non-root but never creates that
account, so container startup will fail; modify the Dockerfile to create the
runtime user and group before the USER non-root instruction (e.g. add commands
that create a group and user like addgroup/useradd or use groupadd/useradd with
a stable UID/GID), ensure ownership of /usr/local/bin/rook and /app/rook.toml is
adjusted (chown) so the non-root user can access them, then keep the existing
USER non-root line; reference the existing USER non-root and the copied files
(/usr/local/bin/rook and /app/rook.toml) when adding the creation and chown
steps.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/proposal.md`:
- Around line 124-127: The proposal's CSRF double-submit flow is inconsistent
because the step "Set-Cookie: csrf_token (HttpOnly, Secure)" prevents the client
from reading the cookie to echo it in the "X-CSRF-Token" header; update the
proposal to either set the csrf_token cookie as readable (remove HttpOnly) so
the client can read and echo it in the POST flow ("Client → POST /api/...
(cookie + X-CSRF-Token header)" and "Validate X-CSRF-Token == csrf_token
cookie"), or replace the double-submit model with a synchronizer token (issue
token in GET /login response body and validate against server-side session) or
another transport (e.g., store token in a JavaScript-accessible storage and use
SameSite/secure cookie only for session) and explicitly call out the chosen
change in the documented flow.

In `@openspec/specs/provider-connections-transport/spec.md`:
- Line 13: Update the ambiguous cross-spec reference in the sentence that points
to `provider-connections.md` so it uses the explicit canonical path
`openspec/specs/provider-connections/spec.md`; locate the line containing
"provider-connections.md" in `spec.md` and replace it with the full path
`openspec/specs/provider-connections/spec.md` to ensure correct navigation and
avoid stale/ambiguous links.

In `@openspec/specs/provider-connections/spec.md`:
- Around line 476-484: The spec declares provider_crud.db_path but the
implementation reads database.db_path and ProviderCrudConfig does not expose
db_path; reconcile them by either updating the spec to document database.db_path
as the source of truth or changing the code to add db_path to ProviderCrudConfig
and make the runtime read provider_crud.db_path (and validate it when
provider_crud.enabled is true alongside ENCRYPTION_PASSPHRASE/ENCRYPTION_SALT);
update any config validation/verification logic and docs so the config key, the
ProviderCrudConfig type, and the runtime lookup all consistently reference the
same symbol (provider_crud.db_path or database.db_path).

---

Duplicate comments:
In `@openspec/changes/archive/2026-05-31-dynamic-provider-registry/tasks.md`:
- Around line 73-79: Update the Sync Phase 5 checklist by marking items 5.6
through 5.12 as completed (change their list markers from [ ] to [x]) so the
tasks.md checklist matches the archived verification state reported by the PR;
specifically edit the lines for "5.6 Add
`refresh_registry_skips_inactive_connections`", "5.7 Add
`refresh_registry_decrypts_and_builds_provider`", "5.8 Add
`refresh_registry_partial_failure_keeps_valid_providers`", "5.9 Add
`refresh_registry_all_failures_results_in_empty_registry`", "5.10 Add
`create_calls_refresh_after_write`", "5.11 Add
`update_calls_refresh_after_write`", and "5.12 Add
`delete_calls_refresh_after_write`" to be checked.

In `@openspec/specs/dynamic-provider-registry/spec.md`:
- Around line 79-80: Update the spec to resolve the contradiction: change the
R8/section 3.2 language that claims the dynamic registry is "always active" to
state that the dynamic registry's CRUD HTTP routes are gated by the feature flag
provider_crud.enabled (matching your architecture/archive docs), or
alternatively add an explicit "Deviation" note in R8 and 3.2 that documents the
implemented behavior and rationale; reference R8, section 3.2, and the
provider_crud.enabled flag in the updated text so readers can reconcile the
behavior with the implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2a0c1cb3-eaeb-41b7-a034-a846a4463086

📥 Commits

Reviewing files that changed from the base of the PR and between d8f4343 and 8d482bf.

⛔ Files ignored due to path filters (49)
  • apps/rook/dashboard/public/icons/android/mipmap-hdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-hdpi/ic_launcher_background.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-hdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-hdpi/ic_launcher_monochrome.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-mdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-mdpi/ic_launcher_background.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-mdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-mdpi/ic_launcher_monochrome.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xhdpi/ic_launcher_background.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xhdpi/ic_launcher_monochrome.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxhdpi/ic_launcher_background.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxhdpi/ic_launcher_monochrome.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxxhdpi/ic_launcher_background.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/android/mipmap-xxxhdpi/ic_launcher_monochrome.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/apple-touch-icon.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/favicon.ico is excluded by !**/*.ico
  • apps/rook/dashboard/public/icons/icon-192-maskable.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/icon-192.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/icon-512-maskable.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/icon-512.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-20@2x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-20@2x~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-20@3x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-20~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-29.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-29@2x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-29@2x~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-29@3x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-29~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-40@2x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-40@2x~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-40@3x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-40~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-60@2x~car.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-60@3x~car.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon-83.5@2x~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon@2x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon@2x~ipad.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon@3x.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon~ios-marketing.png is excluded by !**/*.png
  • apps/rook/dashboard/public/icons/ios/AppIcon~ipad.png is excluded by !**/*.png
  • docs/assets/rook.png is excluded by !**/*.png
  • docs/assets/rook.svg is excluded by !**/*.svg
📒 Files selected for processing (43)
  • .dockerignore
  • .github/workflows/ci.yml
  • Dockerfile.dev
  • Dockerfile.dev.alpine
  • apps/rook/dashboard/index.html
  • apps/rook/dashboard/public/icons/README.txt
  • apps/rook/dashboard/public/icons/android/mipmap-anydpi-v26/ic_launcher.xml
  • apps/rook/dashboard/public/icons/ios/Contents.json
  • apps/rook/dashboard/public/icons/manifest.json
  • dev/Dockerfile
  • dev/Dockerfile.runtime
  • dev/Dockerfile.ubuntu
  • openspec/ARCHITECTURE.md
  • openspec/DOMAIN.md
  • openspec/archive/security-authz-architecture-notes/apply-progress.md
  • openspec/archive/security-authz-architecture-notes/tasks.md
  • openspec/archive/security-authz-architecture-notes/verification_summary.md
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/apply-progress.md
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/design.md
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/proposal.md
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/spec.md
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/state.yaml
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/tasks.md
  • openspec/changes/archive/2025-05-31-security-authz-architecture-notes/verification_summary.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/archive-report.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/design.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/spec.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/tasks.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/verify-report.md
  • openspec/changes/archive/2026-05-31-provider-connections/archive-report.md
  • openspec/changes/archive/2026-05-31-provider-connections/design.md
  • openspec/changes/archive/2026-05-31-provider-connections/proposal.md
  • openspec/changes/archive/2026-05-31-provider-connections/spec.md
  • openspec/changes/archive/2026-05-31-provider-connections/state.yaml
  • openspec/changes/archive/2026-05-31-provider-connections/tasks.md
  • openspec/changes/archive/2026-05-31-provider-connections/verify-report.md
  • openspec/changes/dynamic-provider-registry/verify-report.md
  • openspec/changes/provider-connections/state.yaml
  • openspec/specs/dynamic-provider-registry/design.md
  • openspec/specs/dynamic-provider-registry/spec.md
  • openspec/specs/provider-connections-transport/spec.md
  • openspec/specs/provider-connections/design.md
  • openspec/specs/provider-connections/spec.md
💤 Files with no reviewable changes (7)
  • openspec/archive/security-authz-architecture-notes/tasks.md
  • openspec/changes/provider-connections/state.yaml
  • openspec/archive/security-authz-architecture-notes/verification_summary.md
  • openspec/archive/security-authz-architecture-notes/apply-progress.md
  • openspec/changes/dynamic-provider-registry/verify-report.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/spec.md
  • openspec/changes/archive/2026-05-31-dynamic-provider-registry/design.md

Comment thread .github/workflows/ci.yml
name: SonarCloud
runs-on: ubuntu-latest
needs: [test]
if: secrets.SONAR_TOKEN != ''

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show relevant section around the referenced line(s)
sed -n '150,220p' .github/workflows/ci.yml | nl -ba | sed -n '1,120p'

Repository: dallay/cortex

Length of output: 100


🌐 Web query:

GitHub Actions jobs.<job_id>.if secrets context not allowed

💡 Result:

In GitHub Actions, you cannot directly use the secrets context in a jobs.<job_id>.if conditional expression [1][2][3]. This is a documented limitation implemented for security reasons [3]. If you attempt to reference secrets in a job-level if statement, the workflow will fail with an "Unrecognized named-value" error [1][3]. To conditionally run a job based on the presence or value of a secret, use the following recommended workarounds: 1. Use job-level environment variables: Instead of checking the secret in the job's if condition, define the secret as an environment variable within the job or step, and then perform the conditional check at the step level [2][3]. yaml jobs: my_job: runs-on: ubuntu-latest steps: - name: Run only if secret is set if: env.MY_SECRET != '' env: MY_SECRET: ${{ secrets.MY_SECRET }} run: echo "Secret is available" 2. Perform pre-check jobs: If you need to skip an entire job based on a secret's status, use a preceding job to check the secret and output a result. You can then use the needs context in the subsequent job's if conditional to trigger or skip it based on that output [3]. yaml jobs: check_secret: runs-on: ubuntu-latest outputs: has_secret: ${{ steps.check.outputs.defined }} steps: - id: check run: echo "defined=${{ secrets.MY_SECRET != '' }}" >> $GITHUB_OUTPUT dependent_job: needs: [check_secret] if: needs.check_secret.outputs.has_secret == 'true' runs-on: ubuntu-latest steps: - run: echo "Secret exists, running job." For further context on available contexts, refer to the official GitHub Actions context availability documentation, which explicitly excludes secrets from being valid in jobs.<job_id>.if expressions [4][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

awk 'NR>=170 && NR<=210 {print NR ":" $0}' .github/workflows/ci.yml

Repository: dallay/cortex

Length of output: 1679


Fix invalid jobs.sonar.if expression referencing secrets

  • .github/workflows/ci.yml currently uses if: secrets.SONAR_TOKEN != '' at job level; GitHub Actions doesn’t allow secrets in jobs.<job_id>.if, which breaks workflow validation.
  • Pin sonarsource/sonarcloud-action@master to a specific commit/SHA (currently unpinned).
💡 Minimal fix
  sonar:
    name: SonarCloud
    runs-on: ubuntu-latest
    needs: [test]
-   if: secrets.SONAR_TOKEN != ''
+   env:
+     SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          persist-credentials: false
-     - uses: sonarsource/sonarcloud-action@master
+     - if: env.SONAR_TOKEN != ''
+       uses: sonarsource/sonarcloud-action@master
        env:
-         SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+         SONAR_TOKEN: ${{ env.SONAR_TOKEN }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if: secrets.SONAR_TOKEN != ''
sonar:
name: SonarCloud
runs-on: ubuntu-latest
needs: [test]
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
steps:
- uses: actions/checkout@v6.0.2
with:
persist-credentials: false
- if: env.SONAR_TOKEN != ''
uses: sonarsource/sonarcloud-action@master
env:
SONAR_TOKEN: ${{ env.SONAR_TOKEN }}
🧰 Tools
🪛 actionlint (1.7.12)

[error] 186-186: context "secrets" is not allowed here. available contexts are "github", "inputs", "needs", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 186, Replace the invalid job-level
condition that references secrets by exposing the secret as an env var and
checking that env var (set workflow or job env: SONAR_TOKEN: ${{
secrets.SONAR_TOKEN }}) and change jobs.sonar.if to use if: env.SONAR_TOKEN !=
'' so the job-level condition uses env instead of secrets (refer to
jobs.sonar.if and env.SONAR_TOKEN); also pin the
sonarsource/sonarcloud-action@master reference to a specific commit SHA (replace
sonarsource/sonarcloud-action@master with
sonarsource/sonarcloud-action@<commit-sha>) to avoid using an unpinned action.

Comment thread dev/Dockerfile Outdated
Comment thread dev/Dockerfile.runtime
Comment thread dev/Dockerfile.ubuntu
Comment thread Dockerfile.dev.alpine
Comment on lines +75 to +76
| SPEC-070 | Per-Key Token Bucket Rate Limiting for CLIENT_API | ✅ IMPLEMENTED | `transport-axum/src/middleware/api_key_rate_limiter.rs` — per-key buckets with configurable capacity/refill |
| SPEC-071 | Rate Limited CLIENT_API Returns 429 | ✅ IMPLEMENTED | Returns 429 with `Retry-After` header and `RATE_LIMITED` code |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Final status conflicts with the stated API key rate-limit deviation.

The summary marks SPEC-070/071 as implemented and “All 71 specs verified,” while Line 116-117 says per-key enforcement is deferred/not active. This should be reported as partial compliance, not full implementation.

Also applies to: 116-117, 126-126

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@openspec/changes/archive/2025-05-31-security-authz-architecture-notes/verification_summary.md`
around lines 75 - 76, The verification summary incorrectly marks SPEC-070 and
SPEC-071 as fully implemented despite per-key enforcement being deferred; update
the SPEC-070 and SPEC-071 rows to reflect partial compliance (e.g., "PARTIALLY
IMPLEMENTED" or "DEFERRED - SERVER-WIDE ONLY") and amend the top-line summary
"All 71 specs verified" to the correct partial count and wording; also add a
brief note next to the SPEC-070/SPEC-071 entries (or in the notes section)
stating that the implementation in
transport-axum/src/middleware/api_key_rate_limiter.rs currently provides per-key
buckets configuration but per-key enforcement is not active and therefore
rate-limiting is partially implemented.

Comment on lines +153 to +154
1. **R8 Deviation**: The dynamic registry is gated behind `provider_crud.enabled` (di.rs:54). When `provider_crud.enabled = false`, `manage_connections` is `None` and the registry starts empty (never populated). The spec R8 says "the dynamic registry is always active." The implementation is pragmatically correct — when the feature is disabled, there are no connections to load anyway. However, the spec language is not met.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make the verdict summary consistent with the R8 deviation.

This report flags R8 as a deviation, but later states all R1–R8 are implemented. Reword the verdict bullets so they reflect “implemented with documented R8 deviation” instead of full compliance.

Also applies to: 170-174

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@openspec/changes/archive/2026-05-31-dynamic-provider-registry/verify-report.md`
around lines 153 - 154, Update the verdict summary bullets in the verify report
to accurately reflect the R8 deviation: change any statements that claim full
compliance for R1–R8 to "implemented, with documented R8 deviation" (or similar
wording) and call out the specific deviation about gating the dynamic registry
behind provider_crud.enabled which causes manage_connections to be None when
disabled; ensure the same rewording is applied to the duplicate section around
lines 170–174 so the report consistently states "implemented with documented R8
deviation" rather than full compliance.


This design implements dynamic `ProviderConnection` management as a persisted administrative API. v1 stores connection metadata and encrypted credentials, exposes CRUD/test endpoints, and keeps existing TOML-configured providers as the only request-routing source. Runtime hot registration from SQLite into routing is explicitly future work.

The canonical behavioral contract is `openspec/changes/provider-connections/spec.md`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix stale canonical spec path reference.

openspec/changes/provider-connections/spec.md appears stale/non-existent in this PR layout. Point this to the actual canonical spec location to avoid dead links.

Suggested doc fix
-The canonical behavioral contract is `openspec/changes/provider-connections/spec.md`.
+The canonical behavioral contract is `openspec/specs/provider-connections/spec.md`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The canonical behavioral contract is `openspec/changes/provider-connections/spec.md`.
The canonical behavioral contract is `openspec/specs/provider-connections/spec.md`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/archive/2026-05-31-provider-connections/design.md` at line
7, The line in
openspec/changes/archive/2026-05-31-provider-connections/design.md currently
points to the stale string "openspec/changes/provider-connections/spec.md";
locate the actual canonical spec file for provider-connections in the repository
(the true spec path) and replace that stale reference with the correct
path/filename and a working markdown link, ensuring the referenced file exists
and the link is not broken.

Comment on lines +352 to +364
pub struct ProviderCrudConfig {
pub enabled: bool,
pub db_path: String,
}
```

Default TOML:

```toml
[provider_crud]
enabled = false
db_path = "~/.local/share/cortex/rook/providers.db"
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Config contract conflicts with verified implementation.

This section specifies ProviderCrudConfig.db_path, but your own verification artifacts state implementation uses DatabaseConfig.db_path and ProviderCrudConfig only has enabled. Please align this archived design text or add an explicit “planned vs implemented” note to prevent operator misconfiguration.

Also applies to: 366-371

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openspec/changes/archive/2026-05-31-provider-connections/design.md` around
lines 352 - 364, The design doc currently lists ProviderCrudConfig.db_path but
the implementation uses DatabaseConfig.db_path and ProviderCrudConfig only
contains enabled; update the archived text to match the verified implementation
by removing db_path from ProviderCrudConfig and moving the db_path setting into
the DatabaseConfig section (and update the default TOML accordingly), or
alternatively add a short “planned vs implemented” note that explicitly states
ProviderCrudConfig only has enabled while DatabaseConfig.db_path is used in
production; reference ProviderCrudConfig.enabled, ProviderCrudConfig.db_path,
and DatabaseConfig.db_path when making the change.

Comment thread openspec/changes/archive/2026-05-31-provider-connections/verify-report.md Outdated
yacosta738 and others added 2 commits May 31, 2026 14:52
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yuniel Acosta Pérez <33158051+yacosta738@users.noreply.github.com>
@yacosta738
yacosta738 merged commit 02dbafb into main May 31, 2026
10 of 11 checks passed
@yacosta738
yacosta738 deleted the feat/provider-architecture branch May 31, 2026 13:01
This was referenced Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci CI, tooling, and automation area/docs Documentation and README

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants