Skip to content

Conversation

@ayushjain17
Copy link
Collaborator

@ayushjain17 ayushjain17 commented Jun 18, 2025

AuthZ for org level APIs not supported in this

Summary by CodeRabbit

Release Notes

  • New Features

    • Authorization middleware framework integrated across all API endpoints.
    • Added AUTH_Z_PROVIDER environment configuration option for authorization control.
  • Improvements

    • Enhanced request handling with centralized header and host resolution mechanisms.
    • API endpoints now include standardized security and access control measures.
    • Improved parameter passing for better resource context management across operations.

✏️ Tip: You can customize this high-level summary in your review settings.

@ayushjain17 ayushjain17 requested a review from a team as a code owner June 18, 2025 17:08
@ayushjain17 ayushjain17 force-pushed the auth_z branch 5 times, most recently from 6c52611 to 4928220 Compare June 24, 2025 18:54
@Datron Datron force-pushed the main branch 8 times, most recently from a858147 to 3a83502 Compare July 3, 2025 08:01
@Datron Datron force-pushed the main branch 10 times, most recently from 04b8065 to c899522 Compare July 15, 2025 13:48
@Datron Datron force-pushed the main branch 3 times, most recently from e6a8db3 to 74222bf Compare July 17, 2025 14:22
@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

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

Walkthrough

This PR introduces a comprehensive authorization framework and standardizes handler naming conventions across the backend and frontend. It adds authentication/authorization middleware, procedural macros, and refactors API handlers to consistently use generic names with auth_action attributes. Frontend API functions are updated for SSR support with borrowed parameters and centralized host resolution.

Changes

Cohort / File(s) Summary
Authorization Framework Core
crates/service_utils/src/middlewares/auth_z.rs, auth_z/authorization.rs, auth_z/no_auth.rs
Introduces new authorization middleware layer with Authorizer trait, AuthZ wrapper, AuthZHandler, and NoAuth implementation. Supports pluggable authorization providers (currently disabled). Integrates into Actix Web request lifecycle.
Resource Middleware
crates/service_utils/src/middlewares/resource.rs, workspace_context.rs
Adds middleware to inject Resource and WorkspaceContext into requests. Enables schema/workspace scoping for authorization checks.
Procedural Macros
crates/superposition_derives/src/lib.rs, crates/superposition_macros/src/lib.rs
Introduces #[auth_action] attribute macro for handlers and forbidden! macro for error construction.
Context-Aware Config API Handlers
crates/context_aware_config/src/api/audit_log/handlers.rs, config/handlers.rs, context/handlers.rs, default_config/handlers.rs, dimension/handlers.rs, functions/handlers.rs, type_templates/handlers.rs, variables/handlers.rs
Renames handlers to consistent *_handler convention and adds #[auth_action] attributes. Expands signatures with schema_name and DB context parameters.
Experimentation Platform API Handlers
crates/experimentation_platform/src/api/experiment_groups/handlers.rs, experiments/handlers.rs
Renames handlers to *_handler and adds #[auth_action]. Adjusts parameter handling to derive schema from workspace context.
Core Services Handlers
crates/superposition/src/organisation/handlers.rs, resolve/handlers.rs, webhooks/handlers.rs, workspace/handlers.rs
Consistent handler renaming and #[auth_action] integration. Updates signatures to include User and workspace context. Removes duplicate type module exports.
Type System Updates
crates/service_utils/src/service/types.rs, crates/superposition_types/src/result.rs, api/organisation.rs, api/workspace.rs
Adds Resource enum with workspace scoping logic. Introduces Forbidden error variant. Renames request types (CreateOrganisationRequest → CreateRequest). Default SchemaName now "superposition".
Main Application Setup
crates/superposition/src/main.rs
Integrates AuthZHandler and AuthZManager initialization, adds ResourceMiddleware wrappers for all API resources, adds new /auth route, and wires SSR header extraction.
Frontend API Refactoring
crates/frontend/src/api.rs
Extensive refactor: replaces ServerFnError with String across all modules, switches from get_host() to use_host_server(), updates function parameters from owned Strings to borrowed references.
Frontend Host Resolution
crates/frontend/src/utils.rs, crates/frontend/src/pages/*/utils.rs
Adds SsrSharedHttpRequestHeaders type. Makes get_host() private under non-SSR builds. Replaces get_host() with use_host_server() in all component utilities.
Frontend Pages/Components
crates/frontend/src/pages/*.rs, components/*.rs
Updates resource closures and fetch calls to use workspace instead of tenant, use borrowed references, and handle async/await patterns. Affects default_config, dimensions, experiments, functions, webhooks, and more.
Database Utilities & Cargo
crates/service_utils/src/db/utils.rs, Cargo.toml files
Updates get_database_url to accept optional env_prefix parameter for environment variable prefixing. Adds workspace dependencies on superposition_derives and superposition_macros.
Configuration
.env.example
Updates example ENCRYPTED_KEYS values for clarity. Adds AUTH_Z_PROVIDER=DISABLED configuration.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Middleware as Actix Middleware
    participant AuthZ as AuthZHandler
    participant Resource as Resource Middleware
    participant Authorizer
    participant Handler as Request Handler
    
    Client->>Middleware: HTTP Request
    Middleware->>AuthZ: Extract/Initialize AuthZHandler
    Middleware->>Resource: Inject Resource into Extensions
    Middleware->>Middleware: Pass to Next Layer
    
    rect rgb(200, 220, 255)
    note over Handler: @[auth_action] Handler
    Handler->>Handler: Extract AuthZ<Action> from Request
    Handler->>Authorizer: is_allowed(WorkspaceContext, User, Resource, Action)
    alt Authorization Allowed
        Authorizer-->>Handler: Ok(true)
        Handler->>Handler: Process Request
        Handler-->>Client: 200 OK / Response
    else Authorization Denied
        Authorizer-->>Handler: Ok(false)
        Handler-->>Client: 403 Forbidden
    else Missing Context
        Handler-->>Client: 401 Unauthorized
    end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • knutties

Poem

🐰 Hops through auth gates with graceful cheer,
Resources guarded, contexts clear,
Handlers unified, macros divine,
Frontend and backend in sync align!
Workspace scopes bloom, SSR takes flight,
Authorization's here—what a sight!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: AuthZ setup' accurately describes the primary change: introducing authorization (AuthZ) infrastructure across multiple handler functions and middleware components.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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.

Copy link

@coderabbitai coderabbitai bot left a comment

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 (3)
crates/frontend/src/utils.rs (1)

240-251: Avoid sending an invalid cookie header when no cookie exists.

When cookie is None, the code sends "No Cookie found" as the cookie header value. This sends a malformed/invalid cookie to the server, which could cause unexpected behavior or confuse logging/debugging.

🔎 Proposed fix
     let ssr_headers = use_context::<Option<SsrSharedHttpRequestHeaders>>().flatten();
     let cookie = ssr_headers.and_then(|h| h.cookie.clone());

     let mut request_builder = HTTP_CLIENT.request(method.clone(), url).headers(headers);
     request_builder = match (method, body) {
         (reqwest::Method::GET | reqwest::Method::DELETE, _) => request_builder,
         (_, Some(data)) => request_builder.json(&data),
         _ => request_builder,
     };

-    let response = request_builder
-        .header("cookie", cookie.unwrap_or("No Cookie found".to_string()))
-        .send()
-        .await
-        .map_err(|err| err.to_string())?;
+    let mut request_builder = request_builder;
+    if let Some(cookie_value) = cookie {
+        request_builder = request_builder.header("cookie", cookie_value);
+    }
+
+    let response = request_builder
+        .send()
+        .await
+        .map_err(|err| err.to_string())?;
crates/superposition/src/organisation/handlers.rs (1)

53-59: Inconsistent user identifier usage: get_username() vs get_email().

In create_handler, created_by and updated_by use user.get_username() (lines 53, 59), but in update_handler, updated_by uses user.get_email() (line 86). This inconsistency may cause confusion when auditing who modified records.

Proposed fix - use consistent identifier
 // In update_handler (line 86):
-        .set((req, updated_at.eq(now), updated_by.eq(user.get_email())))
+        .set((req, updated_at.eq(now), updated_by.eq(user.get_username())))

Or alternatively, update create_handler to use get_email() if that's the preferred identifier across the codebase.

Also applies to: 86-86

crates/experimentation_platform/src/api/experiment_groups/handlers.rs (1)

450-455: Blocking thread::sleep inside async context and transaction.

Using std::thread::sleep blocks the current thread, which is problematic in an async runtime. Additionally, sleeping inside a database transaction holds the transaction open longer, potentially causing lock contention. Consider using tokio::time::sleep outside the transaction loop or removing the delay entirely if it's only for rate limiting during backfill.

🔎 Suggested approach

If the delay is for rate limiting, consider processing in batches outside the transaction:

-            for experiment in experiments {
+            for experiment in experiments.iter() {
                 // ... existing logic ...
-                std::thread::sleep(std::time::Duration::from_millis(delay));
             }
+            Ok(results)
+        })?;
+
+    // If delay is needed, apply between separate transactions per experiment

Alternatively, if you must keep the delay, use tokio::time::sleep but note this still extends transaction duration:

// Outside transaction, or restructure to commit per experiment
tokio::time::sleep(std::time::Duration::from_millis(delay)).await;
🧹 Nitpick comments (8)
crates/service_utils/src/db/utils.rs (1)

36-42: Consider validating the env_prefix parameter to prevent unintended behavior.

The env_prefix parameter enables multi-tenant database configuration, but there's an edge case: if a caller passes Some("") (empty string), line 41 will produce "_" as the prefix, resulting in environment variable names like _DB_USER and _DB_HOST.

Consider either:

  1. Documenting that empty strings will produce an underscore prefix
  2. Filtering out empty strings: env_prefix.filter(|s| !s.is_empty()).map(...)
  3. Validating and returning an error for empty strings
🔎 Proposed fix to filter empty strings
-    let env_prefix = env_prefix.map(|s| format!("{s}_")).unwrap_or_default();
+    let env_prefix = env_prefix
+        .filter(|s| !s.is_empty())
+        .map(|s| format!("{s}_"))
+        .unwrap_or_default();
crates/service_utils/src/middlewares/workspace_context.rs (1)

109-111: Extract the hardcoded "test" workspace_id into a constant for clarity.

When enable_workspace_id is false, the code defaults to WorkspaceId(String::from("test")). This is intentional for administrative endpoints like /workspaces and /superposition/organisations where workspace tracking is disabled. However, the magic string should be defined as a constant (e.g., const DEFAULT_DISABLED_WORKSPACE: &str = "test") to improve maintainability and signal intent clearly.

crates/superposition_derives/src/lib.rs (1)

380-387: Consider visibility and uniqueness of generated struct.

The generated AuthZAction* struct is private (no pub modifier). If the handler function is public and used across module boundaries, this could cause visibility issues. Additionally, if two handlers in the same module derive the same action name, there will be a naming conflict.

Consider:

  1. Adding #[allow(non_camel_case_types)] to suppress potential warnings.
  2. Including the function name or a unique suffix in the struct name to prevent conflicts.
🔎 Suggested improvement
     quote! {
+        #[allow(non_camel_case_types)]
         struct #struct_name;

         impl service_utils::middlewares::auth_z::Action for #struct_name {
             fn get() -> String {
                 #action_name.to_string()
             }
         }

         #input_fn
     }
crates/superposition_types/src/result.rs (1)

24-25: Consider clarifying the error message terminology.

The error message displays "unauthorized" but the variant name is Forbidden and returns HTTP 403. In HTTP semantics, 401 Unauthorized means "not authenticated" while 403 Forbidden means "authenticated but not authorized." Consider changing the message to "forbidden" for consistency.

🔎 Proposed fix
-    #[error("unauthorized ( `{0}` )")]
+    #[error("forbidden ( `{0}` )")]
     Forbidden(String),
crates/service_utils/src/middlewares/auth_z.rs (2)

15-15: Unused import: aws_sdk_kms::Client.

This import is only used in commented-out Casbin code. Consider removing it until Casbin support is enabled to avoid dead code warnings.


170-183: Duplicate environment variable reading logic.

AuthZManager::init duplicates the same get_from_env_unsafe("AUTH_Z_PROVIDER").unwrap() pattern as AuthZHandler::init. This creates maintenance burden and inconsistent error handling risk.

Consider extracting a shared helper or consolidating initialization logic.

crates/superposition/src/workspace/handlers.rs (1)

161-161: Minor: Prefer consistent string formatting style.

Line 161 uses string concatenation (org_id.clone().0 + "_" + workspace_name.as_str()) while line 104 uses format! macro. Consider using format! for consistency with the rest of the codebase.

🔎 Suggested change
-    let schema_name = SchemaName(org_id.clone().0 + "_" + workspace_name.as_str());
+    let schema_name = SchemaName(format!("{}_{}", &org_id.0, &workspace_name));
crates/experimentation_platform/src/api/experiment_groups/handlers.rs (1)

398-460: Consider the comment's instruction to remove after backfilling.

The comment on line 398 states "Remove this after backfilling experiment groups". Ensure this endpoint is tracked for removal or is behind a feature flag to prevent accidental use in production after backfill is complete.

Would you like me to open an issue to track the removal of this backfill endpoint after migration is complete?

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9cd0a3b and 7ecaa36.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (65)
  • .env.example
  • crates/context_aware_config/Cargo.toml
  • crates/context_aware_config/src/api/audit_log/handlers.rs
  • crates/context_aware_config/src/api/config/handlers.rs
  • crates/context_aware_config/src/api/context/handlers.rs
  • crates/context_aware_config/src/api/default_config/handlers.rs
  • crates/context_aware_config/src/api/dimension/handlers.rs
  • crates/context_aware_config/src/api/functions/handlers.rs
  • crates/context_aware_config/src/api/type_templates/handlers.rs
  • crates/context_aware_config/src/api/variables/handlers.rs
  • crates/experimentation_platform/Cargo.toml
  • crates/experimentation_platform/src/api/experiment_groups/handlers.rs
  • crates/experimentation_platform/src/api/experiments/cac_api.rs
  • crates/experimentation_platform/src/api/experiments/handlers.rs
  • crates/frontend/src/api.rs
  • crates/frontend/src/components/default_config_form.rs
  • crates/frontend/src/components/default_config_form/utils.rs
  • crates/frontend/src/components/dimension_form.rs
  • crates/frontend/src/components/experiment_conclude_form/utils.rs
  • crates/frontend/src/components/experiment_form.rs
  • crates/frontend/src/components/experiment_form/utils.rs
  • crates/frontend/src/components/experiment_ramp_form/utils.rs
  • crates/frontend/src/components/function_form/utils.rs
  • crates/frontend/src/components/type_template_form/utils.rs
  • crates/frontend/src/pages/compare_overrides.rs
  • crates/frontend/src/pages/config_version.rs
  • crates/frontend/src/pages/config_version_list.rs
  • crates/frontend/src/pages/context_override.rs
  • crates/frontend/src/pages/context_override/utils.rs
  • crates/frontend/src/pages/default_config_list.rs
  • crates/frontend/src/pages/dimensions.rs
  • crates/frontend/src/pages/experiment.rs
  • crates/frontend/src/pages/experiment_group_listing.rs
  • crates/frontend/src/pages/experiment_list.rs
  • crates/frontend/src/pages/function.rs
  • crates/frontend/src/pages/function/function_list.rs
  • crates/frontend/src/pages/function/publish_form.rs
  • crates/frontend/src/pages/function/utils.rs
  • crates/frontend/src/pages/home.rs
  • crates/frontend/src/pages/type_templates.rs
  • crates/frontend/src/pages/webhooks.rs
  • crates/frontend/src/types.rs
  • crates/frontend/src/utils.rs
  • crates/service_utils/Cargo.toml
  • crates/service_utils/src/db/utils.rs
  • crates/service_utils/src/middlewares.rs
  • crates/service_utils/src/middlewares/auth_n/authentication.rs
  • crates/service_utils/src/middlewares/auth_z.rs
  • crates/service_utils/src/middlewares/auth_z/authorization.rs
  • crates/service_utils/src/middlewares/auth_z/no_auth.rs
  • crates/service_utils/src/middlewares/resource.rs
  • crates/service_utils/src/middlewares/workspace_context.rs
  • crates/service_utils/src/service/types.rs
  • crates/superposition/src/main.rs
  • crates/superposition/src/organisation.rs
  • crates/superposition/src/organisation/handlers.rs
  • crates/superposition/src/resolve/handlers.rs
  • crates/superposition/src/webhooks/handlers.rs
  • crates/superposition/src/workspace/handlers.rs
  • crates/superposition_derives/src/lib.rs
  • crates/superposition_macros/src/lib.rs
  • crates/superposition_types/src/api.rs
  • crates/superposition_types/src/api/organisation.rs
  • crates/superposition_types/src/api/workspace.rs
  • crates/superposition_types/src/result.rs
💤 Files with no reviewable changes (1)
  • crates/superposition/src/organisation.rs
🧰 Additional context used
🧬 Code graph analysis (38)
crates/frontend/src/components/type_template_form/utils.rs (1)
crates/frontend/src/utils.rs (1)
  • use_host_server (60-69)
crates/frontend/src/pages/function.rs (1)
crates/frontend/src/api.rs (1)
  • fetch_function (307-324)
crates/frontend/src/components/function_form/utils.rs (1)
crates/frontend/src/utils.rs (1)
  • use_host_server (60-69)
crates/service_utils/src/middlewares/auth_z/authorization.rs (1)
crates/service_utils/src/middlewares/auth_z/no_auth.rs (1)
  • is_allowed (11-20)
crates/frontend/src/components/default_config_form/utils.rs (1)
crates/frontend/src/utils.rs (1)
  • use_host_server (60-69)
crates/frontend/src/components/experiment_form/utils.rs (1)
crates/frontend/src/utils.rs (1)
  • use_host_server (60-69)
crates/frontend/src/pages/config_version_list.rs (2)
crates/frontend/src/pages/workspace.rs (1)
  • workspace (28-285)
crates/frontend/src/api.rs (3)
  • fetch_all (72-89)
  • fetch_all (448-464)
  • fetch_all (989-1012)
crates/frontend/src/pages/context_override.rs (2)
crates/frontend/src/api.rs (6)
  • fetch_context (351-375)
  • fetch (91-108)
  • fetch (120-137)
  • fetch (868-890)
  • fetch (1014-1028)
  • fetch (1163-1186)
crates/frontend/src/pages/dimensions.rs (1)
  • dimensions (25-145)
crates/service_utils/src/middlewares/auth_z/no_auth.rs (1)
crates/service_utils/src/middlewares/auth_z/authorization.rs (1)
  • is_allowed (13-20)
crates/service_utils/src/middlewares/auth_z.rs (2)
crates/service_utils/src/middlewares/auth_z/authorization.rs (1)
  • is_allowed (13-20)
crates/service_utils/src/middlewares/auth_z/no_auth.rs (1)
  • is_allowed (11-20)
crates/superposition_macros/src/lib.rs (1)
crates/experimentation_client/src/interface.rs (1)
  • to_string (45-50)
crates/frontend/src/components/experiment_ramp_form/utils.rs (1)
crates/frontend/src/utils.rs (4)
  • construct_request_headers (202-217)
  • parse_json_response (219-228)
  • request (292-302)
  • use_host_server (60-69)
crates/frontend/src/components/experiment_conclude_form/utils.rs (1)
crates/frontend/src/utils.rs (1)
  • use_host_server (60-69)
crates/superposition_types/src/api/organisation.rs (2)
crates/superposition/src/organisation/handlers.rs (1)
  • organisations (100-102)
crates/superposition/src/workspace/handlers.rs (1)
  • organisations (97-99)
crates/frontend/src/components/dimension_form.rs (2)
crates/frontend/src/pages/dimensions.rs (1)
  • dimensions (25-145)
crates/frontend/src/api.rs (23)
  • None (57-57)
  • None (83-83)
  • None (102-102)
  • None (131-131)
  • None (150-150)
  • None (227-227)
  • None (247-247)
  • None (274-274)
  • None (299-299)
  • None (318-318)
  • None (343-343)
  • None (369-369)
  • None (389-389)
  • None (408-408)
  • None (421-421)
  • None (602-602)
  • fetch (91-108)
  • fetch (120-137)
  • fetch (868-890)
  • fetch (1014-1028)
  • fetch (1163-1186)
  • fetch_functions (282-305)
  • fetch_types (426-443)
crates/superposition_derives/src/lib.rs (1)
crates/service_utils/src/middlewares/auth_z.rs (1)
  • get (28-28)
crates/frontend/src/pages/webhooks.rs (1)
crates/frontend/src/api.rs (1)
  • fetch_webhooks (591-608)
crates/service_utils/src/middlewares/resource.rs (2)
crates/service_utils/src/middlewares/workspace_context.rs (4)
  • new (25-30)
  • new_transform (45-51)
  • call (72-140)
  • req (78-78)
crates/service_utils/src/middlewares/auth_z.rs (6)
  • new_transform (156-161)
  • call (119-122)
  • req (41-41)
  • req (52-52)
  • req (63-63)
  • req (74-74)
crates/frontend/src/components/experiment_form.rs (2)
crates/frontend/src/api.rs (1)
  • fetch_experiment (378-395)
crates/experimentation_platform/src/api/experiments/helpers.rs (1)
  • fetch_experiment (806-818)
crates/superposition/src/resolve/handlers.rs (1)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/context_aware_config/src/api/context/handlers.rs (3)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/service_utils/src/middlewares/auth_n/authentication.rs (1)
  • routes (36-36)
crates/service_utils/src/middlewares/auth_z.rs (1)
  • get (28-28)
crates/service_utils/src/db/utils.rs (1)
crates/service_utils/src/aws/kms.rs (1)
  • decrypt (5-27)
crates/context_aware_config/src/api/audit_log/handlers.rs (1)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/frontend/src/pages/context_override/utils.rs (1)
crates/frontend/src/utils.rs (4)
  • construct_request_headers (202-217)
  • parse_json_response (219-228)
  • request (292-302)
  • use_host_server (60-69)
crates/superposition/src/webhooks/handlers.rs (2)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/service_utils/src/middlewares/auth_z.rs (1)
  • get (28-28)
crates/context_aware_config/src/api/config/handlers.rs (1)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/frontend/src/utils.rs (1)
crates/frontend/src/api.rs (1)
  • execute_value_compute_function (763-803)
crates/experimentation_platform/src/api/experiments/cac_api.rs (5)
crates/context_aware_config/src/helpers.rs (4)
  • state (287-289)
  • state (291-293)
  • state (301-303)
  • state (306-308)
crates/superposition_sdk/src/operation/get_resolved_config_with_identifier/_get_resolved_config_with_identifier_input.rs (2)
  • context_id (56-58)
  • context_id (181-184)
crates/superposition_sdk/src/operation/get_resolved_config_with_identifier/builders.rs (1)
  • context_id (189-192)
crates/superposition_sdk/src/operation/get_resolved_config/_get_resolved_config_input.rs (2)
  • context_id (54-56)
  • context_id (174-177)
crates/superposition_sdk/src/operation/get_resolved_config/builders.rs (1)
  • context_id (189-192)
crates/context_aware_config/src/api/functions/handlers.rs (1)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/superposition_types/src/api/workspace.rs (2)
clients/javascript/sdk/src/models/models_0.ts (2)
  • WorkspaceStatus (1539-1542)
  • WorkspaceStatus (1546-1546)
clients/python/sdk/superposition_sdk/models.py (1)
  • WorkspaceStatus (6615-6617)
crates/frontend/src/pages/experiment.rs (1)
crates/frontend/src/api.rs (7)
  • fetch_experiment (378-395)
  • fetch (91-108)
  • fetch (120-137)
  • fetch (868-890)
  • fetch (1014-1028)
  • fetch (1163-1186)
  • fetch_default_config (40-63)
crates/frontend/src/pages/compare_overrides.rs (3)
crates/frontend/src/pages/dimensions.rs (1)
  • dimensions (25-145)
crates/frontend/src/api.rs (5)
  • fetch (91-108)
  • fetch (120-137)
  • fetch (868-890)
  • fetch (1014-1028)
  • fetch (1163-1186)
crates/superposition_types/src/custom_query.rs (1)
  • all_entries (245-251)
crates/context_aware_config/src/api/type_templates/handlers.rs (3)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/service_utils/src/middlewares/auth_z.rs (1)
  • get (28-28)
crates/service_utils/src/middlewares/auth_n/authentication.rs (1)
  • routes (36-36)
crates/frontend/src/pages/type_templates.rs (2)
crates/frontend/src/pages/workspace.rs (1)
  • workspace (28-285)
crates/frontend/src/api.rs (1)
  • fetch_types (426-443)
crates/experimentation_platform/src/api/experiment_groups/handlers.rs (3)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/service_utils/src/middlewares/workspace_context.rs (1)
  • req (78-78)
crates/experimentation_platform/src/api/experiment_groups/helpers.rs (2)
  • fetch_experiment_group (442-453)
  • member_experiments (98-104)
crates/frontend/src/pages/dimensions.rs (1)
crates/frontend/src/api.rs (5)
  • fetch (91-108)
  • fetch (120-137)
  • fetch (868-890)
  • fetch (1014-1028)
  • fetch (1163-1186)
crates/context_aware_config/src/api/variables/handlers.rs (1)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/context_aware_config/src/api/dimension/handlers.rs (4)
crates/superposition_derives/src/lib.rs (1)
  • auth_action (349-392)
crates/service_utils/src/middlewares/auth_z.rs (1)
  • get (28-28)
crates/service_utils/src/middlewares/auth_n/authentication.rs (1)
  • routes (36-36)
crates/context_aware_config/src/api/dimension/utils.rs (2)
  • dimensions (26-28)
  • dimensions (148-166)
🪛 dotenv-linter (4.0.0)
.env.example

[warning] 38-38: [UnorderedKey] The AUTH_Z_PROVIDER key should go before the AWS_ACCESS_KEY_ID key

(UnorderedKey)


[warning] 40-40: [UnorderedKey] The ENCRYPTED_KEYS key should go before the HOSTNAME key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Provider Tests (py)
  • GitHub Check: Provider Tests (rust)
  • GitHub Check: Provider Tests (kotlin)
  • GitHub Check: Provider Tests (js)
  • GitHub Check: Testing
  • GitHub Check: Check formatting
  • GitHub Check: checks (aarch64-darwin)
🔇 Additional comments (128)
crates/superposition_types/src/api/workspace.rs (1)

6-9: LGTM!

The conditional import for workspaces schema is correctly feature-gated under diesel_derives, which aligns with its usage in the UpdateWorkspaceRequest struct's #[diesel(table_name = workspaces)] attribute on line 79. The import organization is clean and follows the pattern established elsewhere in the file.

crates/service_utils/Cargo.toml (1)

30-30: Dependency correctly added and properly used. The workspace defines superposition_macros = { path = "crates/superposition_macros", version = "0.96.1" }, the entry is correctly formatted and alphabetically ordered, and it's actively used in crates/service_utils/src/middlewares/auth_z.rs for the forbidden and unexpected_error macros.

crates/frontend/src/pages/function/function_list.rs (2)

53-53: LGTM: Improved naming consistency.

The parameter rename from current_tenant to workspace aligns well with the context variable defined on line 29, improving code readability.


55-55: Function signature is compatible with the call.

The fetch_functions signature in crates/frontend/src/api.rs accepts &str parameters for tenant and org_id, and the call at line 55 passes &workspace and &org as borrowed String references, which correctly coerce to &str through Rust's Deref mechanism. No issues found.

crates/service_utils/src/db/utils.rs (4)

2-5: LGTM: Import reformatting improves readability.

The multi-line diesel import formatting is a cosmetic improvement with no functional impact.


43-56: LGTM: Consistent env_prefix usage across database configuration.

The env_prefix parameter is applied consistently across all database configuration variables (DB_USER, DB_PASSWORD, DB_HOST, DB_NAME). The URL-encoding of the decrypted password (line 51) is appropriate for use in PostgreSQL connection strings.


59-70: LGTM: Backward compatibility maintained.

Passing None for the env_prefix parameter preserves the original behavior of init_pool_manager, ensuring backward compatibility for existing initialization code.


20-20: No action needed—removal of URL-encoding is correct for these use cases.

The SUPERPOSITION_TOKEN and OIDC_CLIENT_SECRET are used in contexts where URL-encoding is not required and would be incorrect:

  • superposition_token is used in HTTP Authorization headers and string comparisons, not in URL syntax
  • client_secret is passed to the OIDC library which expects the raw decrypted value for OAuth token exchange

URL-encoding is appropriately retained only for the database password (line 51), which is embedded in a PostgreSQL connection string URL where special characters must be encoded.

crates/frontend/src/pages/function.rs (1)

110-111: LGTM! Parameter passing updated correctly.

The change to pass &workspace and &org_id by reference correctly aligns with the fetch_function signature that expects &str parameters. The destructured owned String values are appropriately borrowed here.

crates/context_aware_config/Cargo.toml (1)

29-29: LGTM! Dependency added to support authorization framework.

The superposition_derives workspace dependency correctly enables the #[auth_action] attribute macro for the authorization framework introduced in this PR.

crates/frontend/src/pages/function/publish_form.rs (1)

35-36: LGTM! Consistent parameter borrowing.

The change to pass &workspace and &org by reference is consistent with the broader frontend refactor and correctly borrows the owned String values extracted on lines 29-30.

crates/superposition_types/src/api.rs (1)

21-21: LGTM! Public module added for organisation API.

The new organisation module is correctly declared as public, expanding the API surface to support organization-level operations referenced in the PR objectives.

crates/frontend/src/pages/webhooks.rs (1)

50-51: LGTM! Consistent workspace terminology and parameter borrowing.

The renaming from current_tenant to workspace improves terminology consistency, and the parameter borrowing correctly matches the fetch_webhooks signature expecting &str references.

.env.example (2)

38-38: LGTM! Authorization provider configuration added.

The AUTH_Z_PROVIDER=DISABLED environment variable correctly documents the new authorization framework. The default DISABLED value is appropriate for development environments.


41-41: LGTM! Encrypted keys example clarified.

The updated comment format better illustrates the expected comma-separated format for the ENCRYPTED_KEYS variable.

crates/experimentation_platform/src/api/experiments/cac_api.rs (1)

226-226: LGTM! Explicit string reference conversion.

Using context_id.as_ref() instead of &context_id is more explicit about the &str conversion for URL concatenation. Both approaches are functionally equivalent for a String parameter.

crates/frontend/src/components/function_form/utils.rs (4)

12-14: LGTM! Centralized host resolution.

The import change correctly replaces get_host with use_host_server, aligning with the frontend refactor that centralizes host resolution logic with SSR support.


36-36: LGTM! Consistent host resolution in create_function.


66-66: LGTM! Consistent host resolution in update_function.


86-86: LGTM! Consistent host resolution in test_function.

All three functions (create_function, update_function, test_function) now consistently use use_host_server() for host resolution, which properly handles both SSR and non-SSR scenarios.

crates/frontend/src/pages/type_templates.rs (1)

43-47: LGTM!

The closure parameter rename from t to workspace and the updated fetch_types call with references (&workspace, &org_id) correctly align with the API signature in api.rs which expects &str parameters. This follows the consistent workspace-centric refactoring pattern across the frontend.

crates/service_utils/src/middlewares/workspace_context.rs (1)

121-133: LGTM!

Using SchemaName::default() instead of hardcoding "public" is cleaner and ensures consistency with the type's Default implementation. The clone/move pattern for workspace_id correctly handles insertion into both the individual extension and the WorkspaceContext struct.

crates/frontend/src/pages/config_version_list.rs (1)

39-44: LGTM!

The closure parameter rename to workspace and the updated fetch_all call with references correctly align with the API signature in api.rs. The async/await pattern with unwrap_or_default() is consistent with the refactoring approach used across other frontend pages.

crates/frontend/src/components/dimension_form.rs (1)

95-125: LGTM!

The refactoring correctly updates the closure to use workspace and org_id parameters, passing them as references to dimensions::fetch, fetch_functions, and fetch_types. This aligns with the API signatures that expect &str parameters. The concurrent fetch pattern using join! and error handling with unwrap_or_default() remain consistent.

crates/frontend/src/pages/default_config_list.rs (1)

84-89: LGTM!

The closure parameter rename and the fetch_default_config call update follow the consistent workspace-centric refactoring pattern. Reference passing (&workspace, &org_id) aligns with API expectations.

crates/frontend/src/types.rs (1)

17-21: LGTM!

The new SsrSharedHttpRequestHeaders struct is appropriately minimal for SSR header propagation. The Option<String> for the cookie field allows for flexible handling when cookies may not be present.

crates/frontend/src/components/default_config_form.rs (1)

102-116: LGTM!

The refactoring correctly updates the closure to receive workspace and org_id, passing them as references to fetch_functions and fetch_types. This is consistent with the API signatures and the broader workspace-centric refactoring pattern across the frontend.

crates/superposition/src/webhooks/handlers.rs (7)

21-29: LGTM!

The endpoints() registration correctly references the renamed handlers (create_handler, list_handler, etc.). This aligns with the #[auth_action] macro requirement that function names end with _handler to automatically derive action names.


31-73: LGTM!

The create_handler correctly applies #[auth_action] and follows the _handler naming convention. The authorization layer is cleanly integrated without modifying the core creation logic.


75-108: LGTM!

The update_handler correctly integrates authorization while preserving the update logic including workspace settings validation and event validation.


110-120: LGTM!

The get_handler correctly applies the #[auth_action] attribute for read authorization.


122-159: LGTM!

The list_handler correctly integrates authorization while maintaining the pagination logic.


186-200: LGTM!

The get_by_event_handler correctly applies authorization for event-based webhook lookup.


161-184: This pattern is intentional and justified by the database audit trigger.

The webhook schema includes a webhooks_audit trigger that automatically invokes event_logger() on every INSERT, UPDATE, and DELETE operation. The UPDATE call before deletion ensures that last_modified_at and last_modified_by are captured by the audit trigger before the record is deleted, creating a complete audit trail. The subsequent DELETE operation also triggers the audit mechanism. This is not redundant—it provides traceability of who made the final modification and when.

Likely an incorrect or invalid review comment.

crates/superposition_derives/src/lib.rs (1)

394-404: LGTM!

The pascal_case helper correctly handles splitting on both - and _, capitalizes the first character of each word, and handles empty segments gracefully.

crates/frontend/src/pages/function/utils.rs (1)

38-57: LGTM!

Good refactor to use borrowed &str for tenant and org_id parameters, avoiding unnecessary allocations. The switch to use_host_server() and centralized request() helper aligns with the broader PR refactor for consistent host resolution and SSR support.

crates/frontend/src/utils.rs (2)

349-361: LGTM!

The rename from tenant to workspace improves clarity and aligns with the naming convention used by execute_value_compute_function. The function call parameters are correctly passed.


71-72: LGTM!

Making get_host() private and cfg-gating it to non-SSR builds is appropriate since it's now only used internally by use_host_server(). This prevents external code from bypassing the centralized host resolution.

crates/frontend/src/components/experiment_ramp_form/utils.rs (1)

6-8: LGTM!

Clean refactor to use use_host_server() for centralized host resolution, consistent with the broader frontend changes in this PR.

Also applies to: 24-24

crates/frontend/src/components/type_template_form/utils.rs (1)

10-10: LGTM!

Consistent application of use_host_server() across all type template operations (create_type, update_type, delete_type), aligning with the centralized host resolution pattern.

Also applies to: 27-27, 57-57, 75-75

crates/frontend/src/components/experiment_conclude_form/utils.rs (1)

11-14: LGTM!

Consistent refactor to use use_host_server() for host resolution in the experiment conclude flow.

Also applies to: 30-30

crates/frontend/src/components/default_config_form/utils.rs (1)

10-12: LGTM!

Consistent application of use_host_server() in both create_default_config and update_default_config functions, following the established pattern.

Also applies to: 35-35, 73-73

crates/service_utils/src/middlewares/resource.rs (1)

1-65: LGTM!

Well-structured Actix Web middleware that follows established patterns (similar to OrgWorkspaceMiddleware). The implementation correctly:

  • Uses Rc<S> for the inner service to enable cloning in async contexts
  • Delegates readiness via forward_ready!
  • Inserts the Resource into request extensions before forwarding to the inner service

The design is clean and integrates well with the AuthZ middleware that retrieves the Resource from extensions (as shown in auth_z.rs:51).

crates/frontend/src/components/experiment_form.rs (1)

389-393: LGTM: Ownership refactor aligns with API signature.

The change from passing owned values to borrowed references (&workspace, &org) correctly matches the fetch_experiment signature that expects &str parameters, as shown in the relevant code snippets.

crates/frontend/src/components/experiment_form/utils.rs (3)

19-21: LGTM: Import updated for SSR support.

Adding use_host_server to imports enables the SSR-compatible host resolution pattern used below.


57-57: LGTM: Host resolution updated for SSR.

The change from get_host() to use_host_server() enables server-side rendering by conditionally routing to localhost when in SSR mode, as shown in the relevant code snippets.


96-96: LGTM: Consistent host resolution for SSR.

Matches the pattern established in create_experiment for SSR compatibility.

crates/frontend/src/pages/compare_overrides.rs (1)

130-136: LGTM: Borrowed references align with API signature.

The dimension resource correctly uses borrowed references (&workspace, &org) matching the dimensions::fetch signature. The async move closure with unwrap_or_default() provides appropriate error handling.

crates/frontend/src/pages/context_override/utils.rs (3)

9-11: LGTM: Import updated for SSR support.

Consistent with the SSR-enabling pattern across the frontend.


40-40: LGTM: Host resolution updated for SSR.

The use_host_server() call enables SSR compatibility by conditionally routing to localhost when appropriate.


74-74: LGTM: Consistent host resolution for SSR.

Matches the SSR pattern established in create_context.

crates/frontend/src/pages/config_version.rs (1)

18-22: LGTM: Borrowed references for snapshot fetch.

The resource correctly passes borrowed references to fetch(), consistent with the API signature and the broader refactoring pattern.

crates/frontend/src/pages/home.rs (1)

169-176: LGTM: Workspace-based fetch with borrowed references.

The dimension resource correctly uses workspace naming and borrowed references, aligning with the broader frontend refactoring. The async move with unwrap_or_default() provides safe defaults.

crates/experimentation_platform/Cargo.toml (1)

24-24: Workspace dependency is properly defined.

superposition_derives is correctly configured in the workspace root Cargo.toml (line 79) with path "crates/superposition_derives" and version "0.96.1", matching the workspace package version.

crates/service_utils/src/middlewares.rs (1)

1-5: All new middleware modules are properly present and the tenant module has been successfully removed.

The module declarations in middlewares.rs are correctly matched by their corresponding files: auth_z.rs, resource.rs, and workspace_context.rs all exist in the filesystem. The auth_z module also includes a subdirectory with additional implementation files (authorization.rs, no_auth.rs). The removal of tenant.rs confirms the migration is complete.

crates/frontend/src/pages/dimensions.rs (1)

36-38: LGTM! Workspace-scoped refactor is consistent.

The change from owned current_tenant to borrowed &workspace improves memory efficiency and aligns with SSR support patterns across the frontend.

crates/frontend/src/pages/experiment_list.rs (1)

82-100: LGTM! Consistent refactor to borrowed workspace references.

All concurrent fetch operations correctly use borrowed references (&workspace, &org_id), which is memory-efficient and consistent with the broader frontend refactor for SSR support.

crates/frontend/src/pages/context_override.rs (1)

429-446: LGTM! Workspace references properly propagated.

The refactor consistently uses borrowed references across all three fetch operations (context, dimensions, default_config), aligning with the workspace-scoped data fetching pattern.

crates/service_utils/src/middlewares/auth_z/authorization.rs (1)

1-38: LGTM! Authorization trait is well-structured.

The Authorizer trait provides a clean async interface for authorization checks using LocalBoxFuture. The Sync + Send bounds are appropriate for middleware usage across async contexts.

The commented-out methods (lines 7-11, 22-38) suggest planned expansion—consider tracking these as follow-up tasks if not already documented.

crates/service_utils/src/middlewares/auth_z/no_auth.rs (1)

1-21: LGTM! Permissive authorizer implementation is appropriate.

The NoAuth implementation correctly provides a pass-through authorizer that always grants access. This is suitable for testing environments or when authorization is disabled.

crates/frontend/src/pages/experiment.rs (1)

64-76: LGTM! Consistent workspace refactor.

The resource closure correctly uses borrowed workspace references across all three concurrent fetch operations, maintaining consistency with the broader frontend refactor.

crates/frontend/src/pages/experiment_group_listing.rs (1)

251-266: LGTM!

The parameter renaming from tenant to workspace aligns with the PR-wide refactoring, and the reference-based passing to fetch_all and dimensions::fetch is correct.

crates/superposition_types/src/api/organisation.rs (2)

1-7: LGTM!

The conditional imports for Diesel's AsChangeset and schema are correctly feature-gated under diesel_derives.


9-28: LGTM!

The struct renames (CreateRequest, UpdateRequest) and the AsChangeset derive with diesel(table_name = organisations) enable direct Diesel update operations when the feature is enabled.

crates/superposition/src/main.rs (5)

38-47: LGTM!

The use_request_headers function correctly extracts the Cookie header for SSR context propagation to Leptos routes.


129-130: LGTM!

AuthZ handler and manager initialization follows the same pattern as the existing AuthN setup.


152-155: LGTM!

Providing the request headers context to Leptos routes enables SSR components to access authentication cookies.


254-260: LGTM!

The /auth scope is correctly configured with ResourceMiddlewareFactory, workspace middleware, and the auth_z_manager is properly shared via app_data.


274-275: Verify middleware execution order.

Actix middleware wraps execute in reverse order of registration. With auth_z registered before auth_n, auth_n will execute first (outer), then auth_z (inner). Confirm this is the intended order—typically authentication should precede authorization.

crates/context_aware_config/src/api/audit_log/handlers.rs (1)

13-24: LGTM!

The handler rename to list_handler and #[auth_action] annotation correctly integrate with the authorization framework. The macro will derive the action name "list" from the function name.

crates/service_utils/src/service/types.rs (3)

71-89: LGTM!

The Resource enum comprehensively covers API resources with consistent snake_case serialization via both Strum and Serde attributes.


91-97: LGTM!

The workspace_for method correctly scopes authorization: Workspace and Auth resources use organisation_id, while other resources use schema_name (workspace-level).


148-152: LGTM!

The Default implementation for SchemaName returning "superposition" is consistent with the OrganisationId default.

crates/superposition/src/resolve/handlers.rs (1)

23-41: LGTM!

The handler rename and #[auth_action] integration follow the established pattern. The clippy::too_many_arguments allowance is reasonable given the authorization parameter injection by the macro.

crates/context_aware_config/src/api/context/handlers.rs (9)

59-71: LGTM!

The endpoint registrations correctly reference all renamed handlers with consistent _handler suffix naming.


73-136: LGTM!

The create_handler is correctly decorated with #[auth_action] and maintains the existing transactional logic with config versioning.


138-191: LGTM!

The update_handler with routes for PUT/PATCH on /overrides correctly integrates authorization while preserving the override update logic.


193-257: LGTM!

The move_handler correctly applies #[auth_action] with the existing move operation logic intact.


259-297: LGTM!

Both get_from_condition_handler and get_handler are correctly authorized and follow the naming convention.


299-421: LGTM!

The list_handler with complex filtering and pagination logic is correctly integrated with authorization.


423-470: LGTM!

The delete_handler correctly applies authorization while maintaining transactional deletion with config versioning.


472-672: LGTM!

The bulk_operations_handler handles the complex transactional bulk operations with proper authorization integration.


674-780: LGTM!

Both weight_recompute_handler and validate_handler are correctly decorated with #[auth_action] following the established pattern.

crates/context_aware_config/src/api/variables/handlers.rs (6)

17-24: LGTM!

The endpoint registrations correctly reference all renamed handlers with the _handler suffix convention.


26-92: LGTM!

The list_handler correctly integrates authorization while maintaining the filtering, sorting, and pagination logic.


94-126: LGTM!

The create_handler correctly applies authorization and creates variables with proper audit fields.


128-145: LGTM!

The get_handler is correctly authorized with schema-scoped variable retrieval.


147-169: LGTM!

The update_handler correctly applies authorization and maintains audit trail with last_modified_at and last_modified_by.


171-197: LGTM!

The delete_handler correctly updates the audit fields before deletion, which is good practice for maintaining an audit trail of who deleted the variable.

crates/service_utils/src/middlewares/auth_z.rs (1)

27-101: Authorization framework implementation looks correct.

The Action trait, AuthZ<A> wrapper, and FromRequest implementation correctly:

  • Extract required extensions from the request
  • Handle missing extensions with appropriate error types
  • Call the authorizer and return forbidden on unauthorized access
crates/context_aware_config/src/api/config/handlers.rs (2)

62-72: Endpoint wiring and handler renames look correct.

The endpoints function correctly registers all renamed handlers, and the naming convention with _handler suffix aligns with the auth_action macro requirements.


433-435: Authorization attributes consistently applied to all handlers.

All handlers (reduce_handler, get_fast_handler, get_handler, resolve_handler, list_version_handler, get_version_handler) correctly have #[auth_action] applied before the route macros, which is the expected order for procedural macro expansion.

Also applies to: 476-478, 565-569, 622-627, 672-674, 715-717

crates/context_aware_config/src/api/default_config/handlers.rs (2)

50-57: Handler wiring and renames correctly implemented.

The endpoints function properly registers all renamed handlers with consistent naming convention.


59-68: Authorization attributes properly applied to all default config handlers.

All CRUD handlers have #[auth_action] correctly positioned before route macros. The #[allow(clippy::too_many_arguments)] on update_handler is appropriately placed.

Also applies to: 166-176, 178-191, 359-366, 429-438

crates/experimentation_platform/src/api/experiments/handlers.rs (3)

102-114: Endpoint wiring correctly updated.

All handlers are properly registered with the new naming convention. Note that conclude_handler, discard_handler, pause_handler, and resume_handler retain their names (they already followed the _handler convention or are being kept as-is).


126-128: Authorization consistently applied across experiment handlers.

All experiment lifecycle handlers (create, conclude, discard, ramp, update, pause, resume, list, get, get_applicable_variants) have #[auth_action] properly applied.

Also applies to: 416-418, 701-703, 924-929, 988-990, 1151-1153, 1174-1176, 1368-1372, 1727-1729, 1828-1830


251-251: Minor improvement in variant ID construction.

Using variant.id.as_ref() instead of &variant.id for string concatenation is a minor stylistic change that's equivalent in behavior.

crates/context_aware_config/src/api/dimension/handlers.rs (3)

50-57: Endpoint wiring correctly implemented for dimension handlers.

All handlers properly registered with consistent _handler naming convention.


59-68: Authorization and annotations correctly applied.

All dimension CRUD handlers have #[auth_action] properly positioned. The #[allow(clippy::too_many_arguments)] on update_handler is appropriately placed before other attributes.

Also applies to: 234-240, 257-270, 437-443, 494-503


7-7: Import adjustment for diesel::delete.

Removing delete from the direct imports and using diesel::delete at line 550 is a valid approach that avoids potential naming conflicts within the transaction closure.

Also applies to: 550-550

crates/context_aware_config/src/api/functions/handlers.rs (3)

32-41: Endpoint wiring correctly updated for function handlers.

All seven handlers properly registered including the function-specific test_handler and publish_handler.


43-50: Authorization correctly applied to all function handlers.

All function management handlers have #[auth_action] properly positioned before route macros.

Also applies to: 122-130, 166-172, 180-187, 216-223, 260-267, 301-309


7-7: Consistent import pattern with diesel::delete.

Same approach as dimension handlers - using fully qualified diesel::delete path to avoid import conflicts.

Also applies to: 248-248

crates/context_aware_config/src/api/type_templates/handlers.rs (2)

26-33: Endpoint wiring correctly updated for type template handlers.

All handlers properly registered with consistent _handler naming.


35-42: Authorization correctly applied to all type template handlers.

All CRUD handlers have #[auth_action] properly positioned.

Also applies to: 72-78, 89-99, 156-163, 182-188

crates/superposition/src/organisation/handlers.rs (3)

24-30: Endpoint wiring correctly updated for organisation handlers.

All handlers properly registered with consistent _handler naming.


32-34: Authorization added to organisation handlers despite PR description.

The PR description states "AuthZ for org level APIs not supported in this", yet #[auth_action] is applied to all organisation handlers. This may be intentional scaffolding for future enforcement, but please verify this is the intended behavior.

Also applies to: 69-73, 92-94, 107-109


41-43: Organisation ID generation uses snowflake-style ID.

Using IdInstance::next_id() with an "orgid" prefix creates human-readable, sortable identifiers. This is a good pattern for external-facing IDs.

crates/superposition/src/workspace/handlers.rs (6)

62-69: LGTM!

The endpoint wiring correctly references the renamed handlers. The service registration pattern is consistent with the handler naming convention adopted across the codebase.


71-86: LGTM!

The get_handler correctly applies the #[auth_action] attribute and the implementation properly filters by org_id ensuring proper workspace isolation.


88-145: LGTM!

The create_handler properly integrates auth via #[auth_action] and uses the User extractor for audit trail (created_by, last_modified_by). The transaction-based workspace creation with schema setup is well-structured.


147-193: LGTM on auth integration.

The update_handler correctly applies #[auth_action] and properly tracks user modifications. The #[routes] macro for PUT/PATCH is appropriate for update operations.


195-250: LGTM!

The list_handler properly applies auth action and filters workspaces by org_id. Pagination logic is correctly implemented with proper handling of the all flag.


280-302: LGTM!

The migrate_schema_handler correctly applies auth action. The transaction ensures atomicity of the schema migration operation.

crates/experimentation_platform/src/api/experiment_groups/handlers.rs (8)

55-65: LGTM!

The endpoint wiring correctly references all renamed handlers including the new backfill_handler.


67-145: LGTM!

The create_handler properly integrates auth via #[auth_action] and correctly uses workspace_request.schema_name throughout. The transaction ensures atomicity of group creation and member assignment.


147-189: LGTM!

The update_handler correctly uses workspace_request.schema_name for both fetching the experiment group and for the update query. The guard against modifying system-generated groups is appropriate.


191-239: LGTM!

The add_members_handler correctly threads workspace_request.schema_name through all helper function calls.


241-284: LGTM!

The remove_members_handler correctly uses workspace_request.schema_name consistently.


349-363: Same pattern as list_handler - uses SchemaName directly.

The get_handler also uses SchemaName instead of WorkspaceContext. This appears to be intentional for read-only operations that don't need the full workspace context.


365-396: LGTM!

The delete_handler correctly uses SchemaName and properly validates that the group has no members before deletion. The update-then-delete pattern within a transaction ensures proper audit trail.


286-347: The difference in parameter usage is intentional. While create_handler, update_handler, add_members_handler, and remove_members_handler use WorkspaceContext, the list_handler correctly uses only SchemaName. This pattern is consistent across the codebase: read-only list handlers uniformly use SchemaName for query scoping, while write operations use the fuller WorkspaceContext. The middleware properly supports both patterns.

crates/frontend/src/api.rs (6)

35-37: LGTM!

The import of construct_request_headers, parse_json_response, request, and use_host_server centralizes the request handling utilities, reducing code duplication across API functions.


40-63: LGTM!

The fetch_default_config function correctly uses the new request pattern with borrowed parameters and proper header construction.


763-803: LGTM!

The execute_value_compute_function function correctly handles the function execution request with proper parameter passing and response parsing.


980-1154: LGTM!

The experiment_groups module is consistently refactored with the new request pattern. All CRUD operations properly use borrowed tenant/org parameters and the centralized request helper.


1156-1186: LGTM!

The audit_log module correctly implements the fetch function with the new request pattern.


416-424: Empty headers for organisation listing are intentional and correctly aligned with the backend.

The /organisations endpoint is configured with OrgWorkspaceMiddlewareFactory::new(false, false), which disables both org_id and workspace_id header validation. The backend handler only requires authentication (via #[auth_action]) but not tenant or organisation context, making this a pre-auth operation that lists all organisations without being scoped to a specific tenant/org. The empty HeaderMap::new() in the frontend is the correct implementation.

@ayushjain17 ayushjain17 force-pushed the auth_z branch 2 times, most recently from c88c74b to 01dfaee Compare January 2, 2026 08:01
org_id: String,
) -> Result<PaginatedResponse<DefaultConfig>, ServerFnError> {
let client = reqwest::Client::new();
tenant: &str,
Copy link
Collaborator

Choose a reason for hiding this comment

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

let us change to workspace - we seem to be doing it in other places.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

will raise a separate PR for this cleanup

@ayushjain17 ayushjain17 merged commit 08b03e0 into main Jan 3, 2026
19 checks passed
@ayushjain17 ayushjain17 deleted the auth_z branch January 3, 2026 12:53
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.

3 participants