Skip to content

Fix/endpoints - #167

Merged
HardMax71 merged 25 commits into
mainfrom
fix/endpoints
Feb 10, 2026
Merged

Fix/endpoints#167
HardMax71 merged 25 commits into
mainfrom
fix/endpoints

Conversation

@HardMax71

@HardMax71 HardMax71 commented Feb 9, 2026

Copy link
Copy Markdown
Owner

Summary by cubic

Streamlined the API by removing unused endpoints, enforcing typed enums, and moving execution business logic into services. DLQ is admin-only; SSE streams require auth and use EventSourceResponse. Grafana alerting uses provisioning (no webhook). OpenAPI, types, docs, frontend, and tests are updated.

  • Refactors

    • Auth: UserRole is an enum; registration creates regular users; admins via POST /api/v1/admin/users; duplicates return 409 "User already exists"; replace /api/v1/auth/verify-token with GET /api/v1/auth/me; repo raises ConflictError.
    • Execution: standardized on ExecutionStatus; added CancelStatus, CancelResult, ExecutionTerminalError; cancel reason required; publish/cancel moved to ExecutionService; Kafka publish_execution_event(status: ExecutionStatus); metrics.record_execution_scheduled() has no arg; idempotency get_cached_json returns None.
    • Endpoints: removed /api/v1/dlq/stats, /api/v1/events/aggregate (and event-type listing), /api/v1/alerts/grafana, and /api/v1/health/ready; DLQ routes require admin_user; events/admin routes return model_validate results; SSE requires current_user and returns EventSourceResponse; Saved Scripts and Saga use current_user via DI; notifications mark_as_read returns 204 and delete returns a message.
    • Schemas/Docs: Replay SessionSummary now nests config {replay_type, target}; UserResponse includes role, is_active, is_superuser; ExecutionResult.status can be null; removed TokenValidationResponse; Grafana docs switched to provisioning; OpenAPI/types regenerated.
  • Migration

    • Replace /api/v1/auth/verify-token with GET /api/v1/auth/me and update frontend auth.
    • Adopt enums UserRole, ExecutionStatus, CancelStatus across API/types.
    • Remove any calls to /api/v1/dlq/stats, /api/v1/events/aggregate, /api/v1/alerts/grafana, and /api/v1/health/ready.
    • Read replay_type and target from SessionSummary.config.
    • Do not send role on registration; create admins via /api/v1/admin/users.
    • Update integrations: metrics.record_execution_scheduled() (no status arg); Kafka publish_execution_event(status: ExecutionStatus).
    • Admin delete user response: rely on user_deleted flag (message field removed).

Written for commit 67e7d5c. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Login/registration now reflect persisted user roles; duplicate-registration message changed to "User already exists".
    • Client-side auth now verifies via current user profile fetch and stores CSRF/user info from profile.
  • Schema Updates

    • LoginResponse and UserResponse role is strongly typed and required; is_active and is_superuser are now required. Token-validation response removed.
  • Breaking Changes

    • Removed token-verify endpoint, DLQ statistics, and event-aggregation/event-type listing endpoints and related public types.
  • Tests

    • Tests updated to use profile-based verification and adjusted DLQ/event tests accordingly.

@coderabbitai

coderabbitai Bot commented Feb 9, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removed the /verify-token endpoint and TokenValidationResponse; auth verification now uses current-user profile fetching. User role typing standardized to UserRole. Duplicate-email conflict handling moved to the user repository. DLQ statistics, event-aggregation, and related types/endpoints were removed. Frontend SDK/types, auth store, interceptors, OpenAPI and tests updated accordingly.

Changes

Cohort / File(s) Summary
Backend — Auth & user
backend/app/api/routes/auth.py, backend/app/db/repositories/user_repository.py, backend/app/schemas_pydantic/user.py
Removed /verify-token route and TokenValidationResponse; login/register now use UserRole and return validated Pydantic responses; create_user now catches DuplicateKeyError and raises ConflictError("User already exists").
Backend — DLQ removals
backend/app/api/routes/dlq.py, backend/app/db/repositories/dlq_repository.py, backend/app/dlq/models.py, backend/app/dlq/__init__.py, backend/app/schemas_pydantic/dlq.py
Removed DLQ statistics models, get_dlq_stats repository method and /stats endpoint; pruned related exports and types.
Backend — Events aggregation removal
backend/app/api/routes/events.py, backend/app/db/repositories/event_repository.py, backend/app/domain/events/..., backend/app/schemas_pydantic/events.py, backend/app/services/event_service.py
Deleted event aggregation and event-type listing endpoints, repository/service methods, EventAggregationResult type and EventAggregationRequest schema; adjusted response constructions to use model_validate(..., from_attributes=True).
Backend — Execution / Idempotency & cancellation
backend/app/api/routes/execution.py, backend/app/services/execution_service.py, backend/app/core/providers.py, backend/app/domain/execution/*, backend/app/domain/enums/execution.py
Added idempotent execution path and cancel_execution with new CancelResult/ExecutionTerminalError/CancelStatus types; ExecutionService now depends on IdempotencyManager (removed EventRepository dependency); provider wiring updated.
Backend — Metrics & minor enums
backend/app/core/metrics/execution.py, backend/app/db/repositories/admin/admin_events_repository.py, backend/app/domain/enums/__init__.py
Changed record_execution_scheduled signature (removed status param); switched literal statuses to ExecutionStatus enum; exported new CancelStatus.
Backend — Middleware & tests
backend/app/core/middlewares/cache.py, backend/tests/conftest.py, backend/tests/e2e/*, backend/tests/e2e/db/repositories/*, backend/tests/e2e/dlq/*, backend/tests/unit/*
Removed cache rule for /api/v1/auth/verify-token; tests updated to use UserRole, removed verify-token and DLQ-stats tests, updated expectations (e.g., "User already exists"); many tests switched to admin client for DLQ flows.
Frontend — Auth store, interceptors & tests
frontend/src/stores/auth.svelte.ts, frontend/src/lib/api-interceptors.ts, frontend/src/stores/__tests__/auth.test.ts
Verification now fetches /api/v1/auth/me (profile) instead of verify-token; auth store derives userId/email/role from profile and reads CSRF from cookie; interceptors removed verify-token from auth endpoints; tests adapted to profile-based mocks.
Frontend — API SDK / types / index
frontend/src/lib/api/sdk.gen.ts, frontend/src/lib/api/types.gen.ts, frontend/src/lib/api/index.ts
Removed generated verifyToken API and related DLQ/aggregate API typings; changed LoginResponse.role and UserResponse to UserRole; updated exported SDK/type lists to match pruned API surface.
Docs / OpenAPI
docs/reference/openapi.json
Removed /api/v1/auth/verify-token and TokenValidationResponse; removed DLQ stats and event-aggregate/type endpoints/schemas; updated user/login schemas to reference UserRole and mark role, is_active, is_superuser, user_id required; changed register 409 description to "User already exists".

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant FrontendStore as Frontend\nAuth Store
  participant API as Backend\nAPI (/api/v1/auth)
  participant DB as User\nRepository/DB

  Client->>FrontendStore: trigger verifyAuth / initialize
  FrontendStore->>API: GET /api/v1/auth/me
  API->>DB: validate session/token & fetch user profile
  DB-->>API: user profile (username, email, role, is_active)
  API-->>FrontendStore: 200 OK + profile
  FrontendStore->>FrontendStore: set user context (userId, userEmail, role), read CSRF cookie
  FrontendStore-->>Client: auth confirmed (state updated)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nibbled tokens down to a thread,
Now I hop to profiles where users are fed.
Roles wear tidy enums, duplicates get checked,
DLQ stats hopped off — fewer things to inspect.
Fresh carrots, light code, and tests pass ahead!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Fix/endpoints' is vague and generic, providing minimal information about the substantial changes in this pull request. Consider using a more descriptive title that highlights the main changes, such as 'Refactor auth and execution to use enums; remove verify-token, DLQ stats, and event aggregation endpoints' or 'Switch to UserRole and ExecutionStatus enums, remove deprecated endpoints'.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 80.95% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/endpoints

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@backend/app/api/routes/auth.py`:
- Around line 168-176: The code currently uses the request-supplied user.role
when building DomainUserCreate which allows privilege escalation; change the
creation to always set role to UserRole.USER (import UserRole from
app.domain.enums if missing) instead of user.role — e.g. keep hashed_password =
security_service.get_password_hash(user.password) and pass role=UserRole.USER
into DomainUserCreate so self-registered accounts cannot set elevated roles.

In `@backend/app/db/repositories/user_repository.py`:
- Around line 21-24: The DuplicateKeyError catch in the doc.insert() flow
currently always raises ConflictError("Email already registered"), which
mislabels non-email unique violations; modify the except block for
DuplicateKeyError to inspect e.details (or e.args) to determine the conflicting
key (e.g., check for "email", "username", "user_id" in the error detail) and
raise a contextual ConflictError like "Email already registered" or "Username
already registered" accordingly, falling back to a generic "User already exists"
if the key can't be determined; keep the original exception as the cause (raise
... from e) and update any tests that assert the exact message in
UserDocument-related operations.

Comment thread backend/app/api/routes/auth.py
Comment thread backend/app/db/repositories/user_repository.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 3 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="backend/app/db/repositories/user_repository.py">

<violation number="1" location="backend/app/db/repositories/user_repository.py:24">
P3: DuplicateKeyError can be raised for unique username or user_id as well as email, so always returning "Email already registered" can mislead clients. Use a generic conflict message or detect which field is duplicated.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/app/db/repositories/user_repository.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
docs/reference/openapi.json (1)

16017-16090: ⚠️ Potential issue | 🟡 Minor

Document is_superuser as legacy; role is the source of truth.

The backend always returns role, is_active, and is_superuser as required fields in UserResponse. However, is_superuser is always initialized to false and never modified in the service layer—authorization decisions should use role (UserRole enum) instead. Add documentation to clarify this legacy field and guide clients to prefer role.

✍️ Recommended documentation clarification
           "is_superuser": {
             "type": "boolean",
-            "title": "Is Superuser"
+            "title": "Is Superuser",
+            "description": "Legacy field; always false. Use `role` for authorization decisions."
           },
🧹 Nitpick comments (2)
frontend/src/stores/auth.svelte.ts (1)

219-219: CSRF cookie value may need decodeURIComponent.

The regex extracts the raw cookie value, but cookie values can be URI-encoded. If the CSRF token ever contains characters like =, %, or ;, the raw match won't give you the correct value.

Suggested fix
-                this.csrfToken = document.cookie.match(/(?:^|;\s*)csrf_token=([^;]*)/)?.[1] ?? null;
+                const rawCsrf = document.cookie.match(/(?:^|;\s*)csrf_token=([^;]*)/)?.[1];
+                this.csrfToken = rawCsrf ? decodeURIComponent(rawCsrf) : null;
frontend/src/stores/__tests__/auth.test.ts (1)

241-304: Consider adding a test for CSRF cookie extraction in verifyAuth.

The verifyAuth method now reads csrfToken from document.cookie (Line 219 of auth.svelte.ts) instead of from the API response. None of the existing tests verify that authStore.csrfToken is correctly set after verifyAuth succeeds. A test that sets document.cookie with a csrf_token value and asserts authStore.csrfToken after verification would close this gap.

…ger, extra endpoint isnt used at all

- also register endpoint fix (instead of calling register with role allowing default users to create admins, - letting only admins in admin/users do it, also fix for conftest setting admin for CI tests)
…o removed uncalled endpoints and tests for them

+ regen of types+openapi spec
…, also xx_id - passed indirectly, without casts to str(), also in cancel request - reason is not nullable, also cancel status - strEnum

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 11 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="backend/app/services/execution_service.py">

<violation number="1" location="backend/app/services/execution_service.py:350">
P1: Possible race condition: when `is_duplicate` is True, the cached result may not exist yet if a concurrent request is still in-flight. `get_cached_json` will raise `AssertionError` in that case. Consider checking whether the result is actually available (or returning a 409/retry-after response for in-progress duplicates).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/app/services/execution_service.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
backend/app/core/metrics/execution.py (1)

89-96: ⚠️ Potential issue | 🟠 Major

Add missing executions_scheduled counter—currently record_execution_scheduled() incorrectly increments executions_assigned.

The class has separate counters for executions_assigned and executions_queued, but record_execution_scheduled() increments executions_assigned instead of a dedicated executions_scheduled counter. This eliminates observability between the "assigned" and "scheduled" lifecycle states.

Create self.executions_scheduled in _create_instruments() and update line 96 to increment it:

self.executions_scheduled = self._meter.create_counter(
    name="executions.scheduled.total", description="Total number of executions scheduled", unit="1"
)

Then change record_execution_scheduled() to:

def record_execution_scheduled(self) -> None:
    self.executions_scheduled.add(1)
🤖 Fix all issues with AI agents
In `@backend/app/services/execution_service.py`:
- Around line 258-261: The terminal state check currently defines
terminal_states = {ExecutionStatus.COMPLETED, ExecutionStatus.FAILED,
ExecutionStatus.TIMEOUT} and raises ExecutionTerminalError when current_status
is in that set; add ExecutionStatus.ERROR to that set so ERROR is treated as
terminal (i.e., change terminal_states to include ExecutionStatus.ERROR) in the
cancel_execution path where this check occurs.
- Around line 272-279: The ExecutionCancelledEvent is being created without
setting aggregate_id, so update its constructor calls (the
ExecutionCancelledEvent instantiation at the current location and the other
occurrence later in the file) to include aggregate_id=execution_id so events can
be retrieved by get_events_by_aggregate; mirror the pattern used by
ExecutionRequestedEvent / ExecutionCompletedEvent / ExecutionFailedEvent and
keep the subsequent await self.producer.produce(event_to_produce=event,
key=execution_id) call unchanged.
- Around line 349-355: The current branch returns cached JSON whenever
idempotency_result.is_duplicate is true, but it doesn't check
idempotency_result.has_cached_result or the idempotency_result.status, so
get_cached_json can assert when no output was saved; update the logic around
idempotency_result.is_duplicate to first check
idempotency_result.has_cached_result (or inspect idempotency_result.status for
FAILED) and only call self.idempotency_manager.get_cached_json(...) and
DomainExecution.model_validate_json(cached_json) when a cached result exists,
otherwise surface/raise the appropriate error or trigger a retry path instead of
calling get_cached_json.
🧹 Nitpick comments (3)
backend/app/schemas_pydantic/execution.py (1)

159-167: Consider typing status as CancelStatus for consistency.

CancelResponse.status is str while the upstream CancelResult.status is CancelStatus. Since CancelStatus is a StringEnum, using it here would provide better OpenAPI schema documentation and type-level consistency with the rest of the enum migration, without breaking serialization.

♻️ Optional improvement
+from app.domain.enums import CancelStatus
+
 class CancelResponse(BaseModel):
     """Model for execution cancellation response."""
 
     execution_id: str
-    status: str
+    status: CancelStatus
     message: str
     event_id: str | None = Field(None, description="Event ID for the cancellation event, if published")
backend/app/api/routes/execution.py (1)

141-141: Stale comment: no UserResponse to User conversion occurs here.

This comment is a leftover from a previous implementation. Remove it to avoid confusion.

Proposed fix
-    # Convert UserResponse to User object
     client_ip = get_client_ip(request)
backend/app/services/execution_service.py (1)

329-339: Inconsistent service_name and service_version in pseudo-event metadata.

The pseudo-event uses service_name="api" and service_version="1.0.0", while _create_event_metadata (line 114-115) uses service_name="execution-service" and service_version="2.0.0". If these values are used for tracing or auditing, the inconsistency may cause confusion.

Consider reusing _create_event_metadata here:

Proposed fix
         pseudo_event = BaseEvent(
             event_id=str(uuid4()),
             event_type=EventType.EXECUTION_REQUESTED,
             timestamp=datetime.now(timezone.utc),
-            metadata=EventMetadata(
-                user_id=user_id,
-                correlation_id=str(uuid4()),
-                service_name="api",
-                service_version="1.0.0",
-            ),
+            metadata=self._create_event_metadata(user_id=user_id),
         )

Comment thread backend/app/services/execution_service.py Outdated
Comment thread backend/app/services/execution_service.py
Comment thread backend/app/services/execution_service.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 5 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="backend/app/api/routes/sse.py">

<violation number="1" location="backend/app/api/routes/sse.py:17">
P3: These SSE endpoints no longer declare a text/event-stream response class, so the OpenAPI schema will advertise application/json by default. This mismatches the actual EventSourceResponse and can break generated clients/docs. Add response_class=EventSourceResponse so the media type is correctly documented.</violation>

<violation number="2" location="backend/app/api/routes/sse.py:29">
P3: This SSE endpoint no longer declares a text/event-stream response class, so the OpenAPI schema will default to application/json. Add response_class=EventSourceResponse to document the correct SSE media type.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/app/api/routes/sse.py Outdated
Comment thread backend/app/api/routes/sse.py Outdated
@sonarqubecloud

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 8 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="backend/app/schemas_pydantic/execution.py">

<violation number="1" location="backend/app/schemas_pydantic/execution.py:96">
P2: ExecutionResult should keep `status` required; making it optional allows null/omitted status in API responses and breaks consistency with other execution response models.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/app/schemas_pydantic/execution.py
@HardMax71
HardMax71 merged commit b3697d4 into main Feb 10, 2026
18 checks passed
@HardMax71
HardMax71 deleted the fix/endpoints branch February 10, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant