Skip to content

refactor(webui): Rename S3Manager to StreamFilesS3Manager; namespace stream-output AWS env vars.#2195

Open
junhaoliao wants to merge 5 commits intomainfrom
webui-s3manager-refactor
Open

refactor(webui): Rename S3Manager to StreamFilesS3Manager; namespace stream-output AWS env vars.#2195
junhaoliao wants to merge 5 commits intomainfrom
webui-s3manager-refactor

Conversation

@junhaoliao
Copy link
Copy Markdown
Member

@junhaoliao junhaoliao commented Apr 10, 2026

Description

Extracted from the WIP prototype in #2169.

Renames the existing S3Manager Fastify decorator to StreamFilesS3Manager to clarify its role
(serving pre-signed URLs for stream files) and prepare for a second LogsInputS3Manager decorator
in a follow-up PR. Also namespaces the AWS credential env vars from the generic AWS_ACCESS_KEY_ID
/ AWS_SECRET_ACCESS_KEY to CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID /
CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY so they don't collide with future CLP_LOGS_INPUT_AWS_*
vars.

Key changes:

  • S3Manager class: Added a credentials: Nullable<AwsCredentialIdentity> parameter to the
    constructor so explicit credentials can be passed (required because the AWS SDK default credential
    chain no longer finds credentials under the renamed env var names). Settings values are now cast
    to Nullable<string>, removing the need for eslint-disable comments.
  • Decorator rename: FastifyInstance.S3ManagerFastifyInstance.StreamFilesS3Manager
    (interface + decorator + all references in stream-files route).
  • env.ts / .env: Adds CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and
    CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY with empty defaults.
  • docker-compose-all.yaml: Renames AWS_ACCESS_KEY_IDCLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID
    (same for secret key) inside the webui service.
  • Helm webui-deployment.yaml: Renames the same two env vars in the stream_output credentials
    conditional block.
  • Chart.yaml: Bumps chart version to 0.2.1-dev.7.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Scenario 1: TypeScript build

Task: Verify the renamed decorator and updated imports compile without errors.

Command:

cd components/webui/server && npm run build

Output:

> clp-webui-server@0.1.0 build
> tsc

(no errors)

Scenario 2: ESLint

Task: Verify no new lint violations are introduced.

Command:

cd components/webui/server && npx eslint src/plugins/app/S3Manager/index.ts src/plugins/external/env.ts src/routes/api/stream-files/index.ts

Output:

(no output — all clean)

Scenario 3: Verify decorator rename is complete

Task: Confirm no stale references to the old decorator name remain.

Command:

grep -rn '"S3Manager"' components/webui/server/src/

Output:

(no matches)

Explanation: All references to the old S3Manager decorator have been updated to
StreamFilesS3Manager.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for explicit AWS credential configuration for S3 stream output. Users can now optionally provide AWS access key ID and secret access key as environment variables for direct credential authentication.
  • Chores

    • Updated deployment configurations and Helm chart version.

@junhaoliao junhaoliao requested a review from a team as a code owner April 10, 2026 07:10
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 10, 2026

Walkthrough

Adds CLP-namespaced S3 credential environment variables, updates deployment and compose templates to use them, modifies S3Manager to accept optional AWS credentials and renames the Fastify decoration to StreamFilesS3Manager, and updates the stream-files route to use the new decoration.

Changes

Cohort / File(s) Summary
Env / Config
components/webui/server/.env, components/webui/server/src/plugins/external/env.ts
Added CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY to .env and the Fastify env schema / config typing (string defaults).
S3 Manager & Fastify plugin
components/webui/server/src/plugins/app/S3Manager/index.ts
S3Manager constructor updated to accept optional credentials: Nullable<AwsCredentialIdentity>; Fastify module augmentation and decoration renamed from S3ManagerStreamFilesS3Manager; plugin reads new env vars and constructs S3Manager with credentials when provided.
Route use
components/webui/server/src/routes/api/stream-files/index.ts
Replaced checks/usages of fastify.S3Manager with fastify.StreamFilesS3Manager for pre-signed URL generation; fallback behaviour unchanged.
Deployment / Compose
tools/deployment/package-helm/templates/webui-deployment.yaml, tools/deployment/package/docker-compose-all.yaml
Renamed injected environment variables in the webui container from AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYCLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID/CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY (conditional on S3 credentials usage).
Chart version
tools/deployment/package-helm/Chart.yaml
Bumped Helm chart version from 0.3.1-dev.00.3.1-dev.1.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Route as StreamFilesRoute
    participant Fastify
    participant S3Mgr as StreamFilesS3Manager
    participant S3

    Client->>Route: Request stream metadata
    Route->>Fastify: access config & check decorator
    Fastify->>S3Mgr: call getPreSignedUrl(path)
    S3Mgr->>Fastify: read CLP_STREAM_OUTPUT_AWS_* from config (optional)
    S3Mgr->>S3: generate presigned URL (uses credentials if provided)
    S3-->>S3Mgr: presigned URL
    S3Mgr-->>Route: presigned URL
    Route-->>Client: return metadata with URL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: renaming S3Manager to StreamFilesS3Manager and namespacing AWS environment variables for stream output.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch webui-s3manager-refactor

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
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/webui/server/src/plugins/app/S3Manager/index.ts`:
- Around line 85-92: The S3 client config silently omits credentials when only
one of accessKeyId/secretAccessKey is provided, causing unintended SDK
credential fallback; inside the S3Manager initialization (where s3ClientConfig
and variables accessKeyId, secretAccessKey, profile are used) add a validation
that if exactly one of accessKeyId or secretAccessKey is set you immediately
throw or return an error (fail fast) with a clear message about the partial
credential configuration, otherwise continue to set credentials when both are
present and keep the existing profile/region handling; reference s3ClientConfig,
accessKeyId, secretAccessKey, and profile when adding the guard so the check is
colocated with the current config assembly.
🪄 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: 7f7ae897-3b39-4319-8e8b-6c8cc64413c5

📥 Commits

Reviewing files that changed from the base of the PR and between 7d00951 and ce8123a.

📒 Files selected for processing (6)
  • components/webui/server/.env
  • components/webui/server/src/plugins/app/S3Manager/index.ts
  • components/webui/server/src/plugins/external/env.ts
  • components/webui/server/src/routes/api/stream-files/index.ts
  • tools/deployment/package-helm/templates/webui-deployment.yaml
  • tools/deployment/package/docker-compose-all.yaml

Comment on lines +85 to +92
const s3ClientConfig: S3ClientConfig = {
...((accessKeyId && secretAccessKey) ?
{credentials: {accessKeyId, secretAccessKey}} :
{}),
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
...((null !== profile) && {profile}),
region,
};
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

Fail fast on partial credential config to avoid unintended identity fallback.

At Line 86, when only one of the two CLP_STREAM_OUTPUT_* values is set, credentials are silently omitted and SDK default credential resolution is used. That can generate pre-signed URLs with the wrong IAM identity and mask misconfiguration.

Proposed fix
             const {
                 CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID: accessKeyId,
                 CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY: secretAccessKey,
             } = fastify.config;

+            const hasAccessKeyId = "" !== accessKeyId;
+            const hasSecretAccessKey = "" !== secretAccessKey;
+            if (hasAccessKeyId !== hasSecretAccessKey) {
+                throw new Error(
+                    "Both CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and " +
+                    "CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY must be set together."
+                );
+            }
+
             const s3ClientConfig: S3ClientConfig = {
-                ...((accessKeyId && secretAccessKey) ?
+                ...((hasAccessKeyId && hasSecretAccessKey) ?
                     {credentials: {accessKeyId, secretAccessKey}} :
                     {}),
                 // eslint-disable-next-line `@typescript-eslint/no-unnecessary-condition`
                 ...((null !== profile) && {profile}),
                 region,
             };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/webui/server/src/plugins/app/S3Manager/index.ts` around lines 85 -
92, The S3 client config silently omits credentials when only one of
accessKeyId/secretAccessKey is provided, causing unintended SDK credential
fallback; inside the S3Manager initialization (where s3ClientConfig and
variables accessKeyId, secretAccessKey, profile are used) add a validation that
if exactly one of accessKeyId or secretAccessKey is set you immediately throw or
return an error (fail fast) with a clear message about the partial credential
configuration, otherwise continue to set credentials when both are present and
keep the existing profile/region handling; reference s3ClientConfig,
accessKeyId, secretAccessKey, and profile when adding the guard so the check is
colocated with the current config assembly.

- Revert S3Manager class to original constructor (region, profile) with
  eager S3Client init; add optional credentials parameter.
- Revert class docstring (not stream-files-specific).
- controller.py already uses CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID (no
  changes needed).
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
components/webui/server/src/plugins/app/S3Manager/index.ts (1)

84-97: ⚠️ Potential issue | 🟠 Major

Fail fast on partial stream-output credential config.

If only one of CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID / CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY is set, this silently falls back to the SDK default credential chain and can sign URLs with the wrong identity. Reject the partial config before deciding which S3Manager constructor path to take.

Proposed fix
             const {
                 CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID: accessKeyId,
                 CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY: secretAccessKey,
             } = fastify.config;
+
+            const hasAccessKeyId = "" !== accessKeyId;
+            const hasSecretAccessKey = "" !== secretAccessKey;
+            if (hasAccessKeyId !== hasSecretAccessKey) {
+                throw new Error(
+                    "Both CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and " +
+                    "CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY must be set together."
+                );
+            }

             fastify.log.info(
                 {region, profile},
                 "Initializing StreamFilesS3Manager"
             );
             fastify.decorate(
                 "StreamFilesS3Manager",
-                (accessKeyId && secretAccessKey) ?
+                (hasAccessKeyId && hasSecretAccessKey) ?
                     new S3Manager(region, profile, {accessKeyId, secretAccessKey}) :
                     new S3Manager(region, profile)
             );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/webui/server/src/plugins/app/S3Manager/index.ts` around lines 84 -
97, Detect and reject partial stream-output AWS credentials before constructing
the S3Manager: check CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and
CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY (fastify.config) and if exactly one is
set, throw or fail fast with a clear error (do not fall back to SDK defaults);
only call new S3Manager(region, profile, {accessKeyId, secretAccessKey}) when
both are present, otherwise call new S3Manager(region, profile) when neither is
set. Update the initialization of the decorated "StreamFilesS3Manager" to
perform this validation and error out on partial config to avoid accidental
credential mixing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/webui/server/src/plugins/app/S3Manager/index.ts`:
- Around line 84-97: Detect and reject partial stream-output AWS credentials
before constructing the S3Manager: check CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and
CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY (fastify.config) and if exactly one is
set, throw or fail fast with a clear error (do not fall back to SDK defaults);
only call new S3Manager(region, profile, {accessKeyId, secretAccessKey}) when
both are present, otherwise call new S3Manager(region, profile) when neither is
set. Update the initialization of the decorated "StreamFilesS3Manager" to
perform this validation and error out on partial config to avoid accidental
credential mixing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8af4f02e-f66f-4d9c-9473-6e73d37431f1

📥 Commits

Reviewing files that changed from the base of the PR and between ce8123a and fae8ce8.

📒 Files selected for processing (1)
  • components/webui/server/src/plugins/app/S3Manager/index.ts

@junhaoliao junhaoliao requested a review from hoophalab April 10, 2026 07:42
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
components/webui/server/src/plugins/app/S3Manager/index.ts (1)

90-92: ⚠️ Potential issue | 🟠 Major

Fail fast on partial stream-output credentials (still unresolved).

Line 90 still treats partial config as “no credentials”, which can silently fall back to SDK default identity and generate URLs with the wrong IAM principal.

Proposed fix
-            const credentials = (accessKeyId && secretAccessKey) ?
-                {accessKeyId, secretAccessKey} :
-                null;
+            const hasAccessKeyId = "" !== accessKeyId;
+            const hasSecretAccessKey = "" !== secretAccessKey;
+            if (hasAccessKeyId !== hasSecretAccessKey) {
+                throw new Error(
+                    "Both CLP_STREAM_OUTPUT_AWS_ACCESS_KEY_ID and " +
+                    "CLP_STREAM_OUTPUT_AWS_SECRET_ACCESS_KEY must be set together."
+                );
+            }
+            const credentials = (hasAccessKeyId && hasSecretAccessKey) ?
+                {accessKeyId, secretAccessKey} :
+                null;
#!/bin/bash
set -euo pipefail

file="components/webui/server/src/plugins/app/S3Manager/index.ts"

# Show the credential assembly block under review.
nl -ba "$file" | sed -n '80,98p'

# Verify whether a paired-credentials guard already exists.
rg -n 'must be set together|hasAccessKeyId|hasSecretAccessKey' "$file" || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/webui/server/src/plugins/app/S3Manager/index.ts` around lines 90 -
92, The current credential assembly sets credentials to null when only one of
accessKeyId or secretAccessKey is provided, which allows silent fallback to SDK
defaults; update the logic around the credentials variable so it validates
paired credentials: if both accessKeyId and secretAccessKey are present use
{accessKeyId, secretAccessKey}, if neither are present keep null, but if exactly
one is present throw an explicit error (or return a rejected Promise) with a
clear message indicating both accessKeyId and secretAccessKey must be set
together; locate the const credentials assignment and add the guard using
accessKeyId and secretAccessKey to enforce the fail-fast behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/webui/server/src/plugins/app/S3Manager/index.ts`:
- Around line 90-92: The current credential assembly sets credentials to null
when only one of accessKeyId or secretAccessKey is provided, which allows silent
fallback to SDK defaults; update the logic around the credentials variable so it
validates paired credentials: if both accessKeyId and secretAccessKey are
present use {accessKeyId, secretAccessKey}, if neither are present keep null,
but if exactly one is present throw an explicit error (or return a rejected
Promise) with a clear message indicating both accessKeyId and secretAccessKey
must be set together; locate the const credentials assignment and add the guard
using accessKeyId and secretAccessKey to enforce the fail-fast behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3d620cb9-45d8-48b1-bee8-af1914bd8e6d

📥 Commits

Reviewing files that changed from the base of the PR and between fae8ce8 and 065a864.

📒 Files selected for processing (2)
  • components/webui/server/src/plugins/app/S3Manager/index.ts
  • tools/deployment/package-helm/Chart.yaml

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